使用jQuery钩子与AngularJS模型数据同步
作者:vergil 发布时间:January 13, 2016 分类:AngularJS,JavaScript
上一篇博文提到,是由于jQuery.val()方法设置DOM元素的值的时候,并没有触发AngularJS的$digest循环。然后我写了一个directive来解决这个问题。
那是否可以有一个更加通用的方法,让AngularJS适应其他使用val()方法设置值的jQuery插件呢?如何让val()自动触发DOM事件??
jQuery Hooks
向豆浆油条求助,得知jQuery有一个API,称为“hook(钩子)”(怪自己不去看官方文档)。
Hooks可以使用在val(),css(),attr(),prop()这些getter/setter方法上。如果你设置了hook,当你调用这些函数的时候,jQuery会触发你hook定义的方法。
Hooks签名如下:
var someHook = {
get: function(elem) {
// obtain and return a value
return "something";
},
set: function(elem, value) {
// do something with value
}
}
.val() Hooks
valHooks允许我们拦截.val()的功能
HTML:
<input type="text" id="t" />
JavaScript:
$.valHooks.text = {
set: function(elem, val) {
elem.value = 'hello ' + val;
return true;
},
get: function(elem) {
return 'fuck';
}
}
$('#t').val('world!'); //设置值为:hello world!
$('#t').val(); //返回:fuck
.css() Hooks
以后补充
.prop()和.attr() Hooks
以后补充
使用valHooks让jQuery.val()与AngularJS模型数据同步
知道Hooks之后,我们就可以拦截.val()的功能,在设置好值之后,触发一个让AngularJS进入$degist的情况。比如,触发input
事件
Example:
<!doctype html>
<html ng-app="app">
<head>
<script src="http://cdn.bootcss.com/jquery/2.2.0/jquery.min.js"></script>
<script src="http://cdn.bootcss.com/angular.js/1.4.8/angular.min.js"></script>
<script>
$(function(){
$('#setvalue').on('click', function() {
$('#input').val('hello world!');
});
$.valHooks.text = {
set: function(elem, val) {
elem.value = val; //把DOM元素设置为传进来的val值
$(elem).trigger('input'); //触发input事件
return true;
}
};
});
</script>
</head>
<body>
<div>
<input type="text" ng-model="value" id="input" />
<button type="button" id="setvalue">jQuery set value</button>
<p>ng model value is:{{value}}</p>
</div>
</body>
</html>
OK,那么现在,使用val()
方法设置元素的值之后,也可能让AngularJS的模型同步了。
一般情况下,这样子确实可以解决问题,但如果你不想让它触发input事件呢?比如说,你的input事件有另外的功能。
我的思路就是,触发一个自定义事件,写一个directive监听该事件。
Example:
<!doctype html>
<html ng-app="app">
<head>
<script src="http://cdn.bootcss.com/jquery/2.2.0/jquery.min.js"></script>
<script src="http://cdn.bootcss.com/angular.js/1.4.8/angular.min.js"></script>
<script>
$(function(){
$('#setvalue').on('click', function() {
$('#input').val('hello world!');
});
$.valHooks.text = {
set: function(elem, val) {
elem.value = val;
$(elem).trigger('jquery.set.value'); //触发自定义事件
return true;
}
};
});
</script>
</head>
<body>
<div>
<!-- 注意这个input标签使用了jqSetValue组件 -->
<input type="text" ng-model="value" id="input" jq-set-value />
<button type="button" id="setvalue">jQuery set value</button>
<p>ng model value is:{{value}}</p>
</div>
<script>
angular.module('app', []).directive('jqSetValue', function() {
return {
restrict: 'AC',
require: '?ngModel',
link: function(scope, element, attrs, ngModel) {
//设置自定义事件的回调函数
element.on('jquery.set.value', function(event) {
if(!ngModel) return;
scope.$apply(function(){
ngModel.$setViewValue($(element).val());
});
});
}
};
});
</script>
</body>
</html>
很详细
抢沙发,嘻嘻,不错,喜欢
Very Good!