怎么把js封装成angularjs
若以下回答无法解决问题,邀请你更新回答
1个回答
2017-11-07 · 百度知道合伙人官方认证企业
育知同创教育
1【专注:Python+人工智能|Java大数据|HTML5培训】 2【免费提供名师直播课堂、公开课及视频教程】 3【地址:北京市昌平区三旗百汇物美大卖场2层,微信公众号:yuzhitc】
向TA提问
关注
展开全部
与jquery类库的协作
第三方类库中,不得不提的是大名鼎鼎的jquery,现在基本上已经是国内web开发的必修工具了。它灵活的dom操作,让很多web开发人员欲罢不能。再加上已经很成熟的jquery UI 库和大量jquery 插件,几乎是一个取之不尽用之不竭的宝库。然而,它是否能与angularjs结合呢?
很多angularjs原教旨主义者对此持否定态度。他们认为,既然已经使用了angularjs做web应用框架,那就必须避免其他类库的干扰,做纯净的MvvM模式应用。任何类似jquery的dom操作,都是不洁的。把所有和界面相关的, 比如dom操作, 都放在directive中, 这样页面中directive而没有代码,跟JSF思想一致。MVVM,DSL,组件化的思想这才是web的趋势。嗯,想法很好,原教旨主义者想法都是这么纯洁。但事实情况是,使用了angularjs我们就离不开jquery。
众所周知,angularjs里面事实上已经内置了jquery lite.,而且angularjs源码中很多方法直接就是使用jquery方法。例如angularjs的事件绑定机制。既然先知们都在用,我们又何苦不用?组件化的思想没有错,但没必要因此把自己的手脚绑住。唯一要注意的问题是,不要用jquery的代码破坏了angularjs的结构。对此我的原则如下,不足之处还请指出:
模块划分、服务、路由、依赖注入等重要方面上都得使用angularjs的方式,只有某些具体内容(通常是一些Ui)才使用jquery。 避免在controller里面写了一堆直接操作dom元素的 jquery代码。使用angularjs的模板绑定机制。 常用的组件要用angularjs的方法抽取出来,但组件具体实现则不必纠结于是否使用jquery及其插件。 .使用第三方类库时,在变量和函数命名时有特殊标记(通常是加上这个类库名的缩写)。
jquery,更是建议作为angularjs的依赖,先于angularjs加载进来。
事实上,选择了angularjs这样的框架中德中等重量级选手,就意味着你必须添加其他类库。而jquery,更是建议作为angularjs的依赖,先于angularjs加载进来。因为在查看angularjs API的时候,我已经发现,其中许多功能,事实上是依赖于jquery的。典型的例子,就是官网的ng-blur指令。
<input type="text" ng-model="name" ng-blur="checkname()" > ng-blur指令,是在焦点离开某个元素时触发的指令。对于上例,即在焦点离开该文本输入框时,触发checkname()函数。
看起来很简单,但是你如果真的使用了这个指令,你就会发现它根本不起效果。在仔细查看文档后,我才发现这实际是先知们使用jquery的blur方法实现的函数(而且事实上根本没有真正实现并放在当前的版本里)。那么就算我们想写一个,离开jquery原生库是不行的,因为blur方法并未封装到angularjs内带的jquery lite里。换句话说,必须先载入完整的jquery才能使用。于是,我干脆自己写了一个标签:
?
12345678910111213141516
/** angular directive onBlur** @description my ng-blur* @require jquery*/$compileProvider.directive('onBlur', function() { return { restrict : 'A', link : function(scope, elm, attrs) { elm.bind('blur', function() { scope.$apply(attrs.onBlur); }); } };});
这已经很好了。
但是还不够完美。由于$apply方法接受函数的问题,所以直接像上面这样写,有可能导致angularjs运行时报错:$apply already in progress
避免这个问题的发生,则需要对$apply方法进行加工:
?
123456789101112131415161718192021
/* factory function safeApply** @description If you find yourself triggering the '$apply already in progress' error while developing with Angular.JS* (for me I find I hit most often when integrating third party plugins that trigger a lot of DOM events),* you can use a 'safeApply' method that checks the current phase before executing your function.** @param scope, the action scope, mostly is the topmost controller* @param fn, the function which you want to apply into scope* @see https://coderwall.com/p/ngisma*/.factory('safeApply', function($rootScope) { return function(scope, fn) { var phase = scope.$root.$$phase; if (phase == '$apply' || phase == '$digest') { if (fn && ( typeof (fn) === 'function')) { fn(); } } else { scope.$apply(fn); } }});
那么之前的onblur标签,就应该改为:
?
12345678910111213141516
/** angular directive onBlur** @description my ng-blur* @require jquery*/$compileProvider.directive('onBlur', function(safeApply) { return { restrict : 'A', link : function(scope, elm, attrs) { elm.bind('blur', function() { safeApply(scope, attrs.onBlur); }); } };});
以上代码我已经加入了自己的angular_extend模块,在自己的项目中使用了,效果很好。
将jquery 插件用angularjs的方式封装成组件的例子
icheck是一个jquery插件,用于跨浏览器美化Checkbox和Radio按纽。关于它的介绍,在http://www.bootcss.com/p/icheck/
一般来说,它的使用方法是在dom载入后加一段jquery代码:
?
1234567
$('input').iCheck({ labelHover : false, cursor : true, checkboxClass : 'icheckbox_square-blue', radioClass : 'iradio_square-blue', increaseArea : '20%'});
但是既然要放在我们的项目里,就不能到处塞这种直接操作dom的jquery代码,既不美观,也不易维护。按照之前所说的原则,最好将其封装成angular指令的模式,放在公共模块里来调用。这里我将我新建的指令命名为ng-icheck。如此,我们只要写在某个checkbox或者radio的html标签里加上一句ng-ickeck即可。具体实现如下:
?
123456789101112131415161718192021222324252627282930313233343536373839
/* * angular directive ng-icheck * * @description icheck is a plugin of jquery for beautifying checkbox & radio, now I complied it with angular directive * @require jquery, icheck * @example <input type="radio" ng-model="paomian" value="kangshifu" ng-icheck> * <input type="checkbox" class="icheckbox" name="mantou" ng-model="mantou" ng-icheck checked> */$compileProvider.directive('ngIcheck', function($compile) { return { restrict : 'A', require : '?ngModel', link : function($scope, $element, $attrs, $ngModel) { if (!$ngModel) { return; } //using iCheck $($element).iCheck({ labelHover : false, cursor : true, checkboxClass : 'icheckbox_square-blue', radioClass : 'iradio_square-blue', increaseArea : '20%' }).on('ifClicked', function(event) { if ($attrs.type == "checkbox") { //checkbox, $ViewValue = true/false/undefined $scope.$apply(function() { $ngModel.$setViewValue(!($ngModel.$modelValue == undefined ? false : $ngModel.$modelValue)); }); } else { // radio, $ViewValue = $attrs.value $scope.$apply(function() { $ngModel.$setViewValue($attrs.value); }); } }); }, };});
在以上代码中值得注意的是:使用了icheck插件后,会生成一个美化过的div覆盖在原来的checkbox或者radio之上,而原来的checkbox或者radio会被影藏。故而,当我们点击它们时,不会直接触发事件,使得绑定到checkbox或者radio上的model值改变。所以我们这里需要重新绑定事件,使用
$ngModel.$setViewValue() 方法来给model赋值。具体逻辑,则相根据checkbox和radio而不同。详见以上代码。
第三方类库中,不得不提的是大名鼎鼎的jquery,现在基本上已经是国内web开发的必修工具了。它灵活的dom操作,让很多web开发人员欲罢不能。再加上已经很成熟的jquery UI 库和大量jquery 插件,几乎是一个取之不尽用之不竭的宝库。然而,它是否能与angularjs结合呢?
很多angularjs原教旨主义者对此持否定态度。他们认为,既然已经使用了angularjs做web应用框架,那就必须避免其他类库的干扰,做纯净的MvvM模式应用。任何类似jquery的dom操作,都是不洁的。把所有和界面相关的, 比如dom操作, 都放在directive中, 这样页面中directive而没有代码,跟JSF思想一致。MVVM,DSL,组件化的思想这才是web的趋势。嗯,想法很好,原教旨主义者想法都是这么纯洁。但事实情况是,使用了angularjs我们就离不开jquery。
众所周知,angularjs里面事实上已经内置了jquery lite.,而且angularjs源码中很多方法直接就是使用jquery方法。例如angularjs的事件绑定机制。既然先知们都在用,我们又何苦不用?组件化的思想没有错,但没必要因此把自己的手脚绑住。唯一要注意的问题是,不要用jquery的代码破坏了angularjs的结构。对此我的原则如下,不足之处还请指出:
模块划分、服务、路由、依赖注入等重要方面上都得使用angularjs的方式,只有某些具体内容(通常是一些Ui)才使用jquery。 避免在controller里面写了一堆直接操作dom元素的 jquery代码。使用angularjs的模板绑定机制。 常用的组件要用angularjs的方法抽取出来,但组件具体实现则不必纠结于是否使用jquery及其插件。 .使用第三方类库时,在变量和函数命名时有特殊标记(通常是加上这个类库名的缩写)。
jquery,更是建议作为angularjs的依赖,先于angularjs加载进来。
事实上,选择了angularjs这样的框架中德中等重量级选手,就意味着你必须添加其他类库。而jquery,更是建议作为angularjs的依赖,先于angularjs加载进来。因为在查看angularjs API的时候,我已经发现,其中许多功能,事实上是依赖于jquery的。典型的例子,就是官网的ng-blur指令。
<input type="text" ng-model="name" ng-blur="checkname()" > ng-blur指令,是在焦点离开某个元素时触发的指令。对于上例,即在焦点离开该文本输入框时,触发checkname()函数。
看起来很简单,但是你如果真的使用了这个指令,你就会发现它根本不起效果。在仔细查看文档后,我才发现这实际是先知们使用jquery的blur方法实现的函数(而且事实上根本没有真正实现并放在当前的版本里)。那么就算我们想写一个,离开jquery原生库是不行的,因为blur方法并未封装到angularjs内带的jquery lite里。换句话说,必须先载入完整的jquery才能使用。于是,我干脆自己写了一个标签:
?
12345678910111213141516
/** angular directive onBlur** @description my ng-blur* @require jquery*/$compileProvider.directive('onBlur', function() { return { restrict : 'A', link : function(scope, elm, attrs) { elm.bind('blur', function() { scope.$apply(attrs.onBlur); }); } };});
这已经很好了。
但是还不够完美。由于$apply方法接受函数的问题,所以直接像上面这样写,有可能导致angularjs运行时报错:$apply already in progress
避免这个问题的发生,则需要对$apply方法进行加工:
?
123456789101112131415161718192021
/* factory function safeApply** @description If you find yourself triggering the '$apply already in progress' error while developing with Angular.JS* (for me I find I hit most often when integrating third party plugins that trigger a lot of DOM events),* you can use a 'safeApply' method that checks the current phase before executing your function.** @param scope, the action scope, mostly is the topmost controller* @param fn, the function which you want to apply into scope* @see https://coderwall.com/p/ngisma*/.factory('safeApply', function($rootScope) { return function(scope, fn) { var phase = scope.$root.$$phase; if (phase == '$apply' || phase == '$digest') { if (fn && ( typeof (fn) === 'function')) { fn(); } } else { scope.$apply(fn); } }});
那么之前的onblur标签,就应该改为:
?
12345678910111213141516
/** angular directive onBlur** @description my ng-blur* @require jquery*/$compileProvider.directive('onBlur', function(safeApply) { return { restrict : 'A', link : function(scope, elm, attrs) { elm.bind('blur', function() { safeApply(scope, attrs.onBlur); }); } };});
以上代码我已经加入了自己的angular_extend模块,在自己的项目中使用了,效果很好。
将jquery 插件用angularjs的方式封装成组件的例子
icheck是一个jquery插件,用于跨浏览器美化Checkbox和Radio按纽。关于它的介绍,在http://www.bootcss.com/p/icheck/
一般来说,它的使用方法是在dom载入后加一段jquery代码:
?
1234567
$('input').iCheck({ labelHover : false, cursor : true, checkboxClass : 'icheckbox_square-blue', radioClass : 'iradio_square-blue', increaseArea : '20%'});
但是既然要放在我们的项目里,就不能到处塞这种直接操作dom的jquery代码,既不美观,也不易维护。按照之前所说的原则,最好将其封装成angular指令的模式,放在公共模块里来调用。这里我将我新建的指令命名为ng-icheck。如此,我们只要写在某个checkbox或者radio的html标签里加上一句ng-ickeck即可。具体实现如下:
?
123456789101112131415161718192021222324252627282930313233343536373839
/* * angular directive ng-icheck * * @description icheck is a plugin of jquery for beautifying checkbox & radio, now I complied it with angular directive * @require jquery, icheck * @example <input type="radio" ng-model="paomian" value="kangshifu" ng-icheck> * <input type="checkbox" class="icheckbox" name="mantou" ng-model="mantou" ng-icheck checked> */$compileProvider.directive('ngIcheck', function($compile) { return { restrict : 'A', require : '?ngModel', link : function($scope, $element, $attrs, $ngModel) { if (!$ngModel) { return; } //using iCheck $($element).iCheck({ labelHover : false, cursor : true, checkboxClass : 'icheckbox_square-blue', radioClass : 'iradio_square-blue', increaseArea : '20%' }).on('ifClicked', function(event) { if ($attrs.type == "checkbox") { //checkbox, $ViewValue = true/false/undefined $scope.$apply(function() { $ngModel.$setViewValue(!($ngModel.$modelValue == undefined ? false : $ngModel.$modelValue)); }); } else { // radio, $ViewValue = $attrs.value $scope.$apply(function() { $ngModel.$setViewValue($attrs.value); }); } }); }, };});
在以上代码中值得注意的是:使用了icheck插件后,会生成一个美化过的div覆盖在原来的checkbox或者radio之上,而原来的checkbox或者radio会被影藏。故而,当我们点击它们时,不会直接触发事件,使得绑定到checkbox或者radio上的model值改变。所以我们这里需要重新绑定事件,使用
$ngModel.$setViewValue() 方法来给model赋值。具体逻辑,则相根据checkbox和radio而不同。详见以上代码。
本回答被提问者采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询