AngularJs directive详解及示例代码(2)

  当上面的例子被编译时,编译器会遍历所有节点以寻找directive。{{user}}是一个interpolation directive的例子。ngRepeat又是另外一个directive。但ngRepeat有一个难点。它需要能够很快地为每一个在users.actions中的action制造出新的li的能力。这意味着它为了满足克隆li并且嵌入特定的action(这里是指user的actions的其中一个值)的目的,需要保持一个干净li元素的拷贝,li元素需要被克隆和插入ul元素。但仅仅克隆li元素是不够的。还需要编译li,以便它的directive({{action.descriptions}})能够在正确的scope中被解析。原始的方法,一般会简单地插入一个li元素的拷贝,然后编译它。但编译每一个li元素的拷贝会比较缓慢,因为编译过程需要我们遍历DOM节点树,查找directive并运行它们。如果我们有一个编译,需要通过repeater对100个item进行处理,那么我们将陷入性能问题。

  问题的解决方案,是将编译过程分解为两个步骤。compile阶段识别出所有directive,并且将它们按照优先级进行排序,在linking阶段将特定的scope与特定的li绑定在一起。

  ngRepeat将各个li分开编译以防止编译过程落入li元素中。li元素的编译结果是一个包含所有包含在li元素中的directive的linking function,准备与特定li元素的拷贝进行连接。在运行时,ngRepeat监测表达式,并作为一个item,被加入到一个li元素拷贝的数组,为克隆好的li元素创建新的scope,并调用该拷贝对应的link function。

  总结:

1.编译函数(compile function) - 编译函数在directive中是比较少见的,因为大多数directive只关心与指定的DOM元素工作,而不是改变DOM元素的模版(DOM自身以及内部的结构)。为了优化性能,一些可以被directive实例共享的操作,可以移动到compile函数中。

2.连接函数(link function) - 极少directive是没有link function的。link function允许directive在指定的拷贝后的DOM元素实例上注册监听器,也可以将scope中特定内容复制到DOM中。

五、写一个directive(简易版)

  在这个例子里面,我们将建立一个根据输入格式,显示当前时间的directive。

<!DOCTYPE HTML> <html lang="zh-cn" ng-app="TimeFormat"> <head> <meta charset="UTF-8"> <title>time-format</title> </head> <body> <div ng-controller="MyCtrl"> Date format: <input ng-model="format" type="text"/><hr/> <!--下面使用属性x-current-time,是为了试试上面说的合法命名~~current:time、current-time、current_time、data-current-time -_-!!! --> Current time is : <span x-current-time="format"></span><br/> <button ng-click="remove()">remove the span</button> </div> <script src="https://www.jb51.net/angular-1.0.1.js" type="text/javascript"></script> <script type="text/javascript"> angular.module("TimeFormat", []) //在TimeFormat应用中注册“currentTime”这个directive的工厂方法 //前文提到过,依赖注入,可以直接在function的参数中写入,这里注入了$timeout、dataFilter .directive("currentTime", function (dateFilter) { //这个是上面提到的linking function。(不需要添加compile function,为啥?。。。) return function (scope, element, attr) { var intervalId; //更新对应element的text值,即更新时间 function updateTime() { element.text(dateFilter(new Date(), scope.format)); } //通过watch,监控span对象的currentTime的值(是format这个model值,即input的值!!) //这个方法仅仅在format发生改变的时候执行 scope.$watch(attr.currentTime, function (value) { scope.format = value; updateTime(); }); //当span被去掉的时候,取消更新 element.bind("$destroy", function () { clearInterval(intervalId); }); intervalId = setInterval(updateTime, 1000); }; }).controller("MyCtrl",function($scope,$rootScope) { $scope.format = "M/d/yy h:mm:ss a"; $scope.remove = function() { var oFormat = document.getElementById("myFormat"); if(oFormat) { angular.element(oFormat).remove();//通过这种方式调用remove,可以触发$destroy事件啊!!!试了我N久。。。 } }; }); </script> </body> </html>
 

六、写一个directive(详细版)

  下面是一个创建directive样例(directive对象定义模版)。想看详细列表,请继续往下看。

var myModule = angular.module(...); myModule.directive('directiveName', function factory(injectables) { var directiveDefinitionObject = {   priority: 0,   template: '<div></div>',   templateUrl: 'directive.html',   replace: false,   transclude: false,   restrict: 'A',   scope: false,   compile: function compile(tElement, tAttrs, transclude) {     return {       pre: function preLink(scope, iElement, iAttrs, controller) { ... },       post: function postLink(scope, iElement, iAttrs, controller) { ... }     }   },   link: function postLink(scope, iElement, iAttrs) { ... } }; return directiveDefinitionObject; });

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wzfdwx.html