【AngularJS】——核心特性之指令の执行机制

      上篇文章《【AngularJS】——核心特性之指令》简单的介绍了一下指令的类型和简单应用。那么,指令具体是怎么运行的呢?让我们来一起揭开指令的神秘面纱。


      我们知道,指令的本质其实是一个替换的过程。指令的核心步骤就是compile(编译)和link(连接)。


      1、Link函数

      指令生成出的模板其实没有太多意义,除非它在特定的scope下编译。默认情况下,指令并不会创建新的子scope。更多的,它使用父scope。也就是说,如果指令存在于一个controller下,它就会使用这个controller的scope。 如何运用scope,我们要用到一个叫做 link 的函数。它由指令定义对象中的link属性配置。让我们来改变一下我们的 helloWorld 指令,当用户在一个输入框中输入一种颜色的名称时,Hello World 文字的背景色自动发生变化。同时,当用户在 Hello World 文字上点击时,背景色变回白色。 相应的HTML标记和指令如下:

     

<html ng-app="myapp">
<head>
   <title>Angular JS Custom Directives</title>
   <!-- 引入ng库 -->
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>

   <script>
	var app = angular.module('myapp', []);

	app.directive('helloWorld', function() {
  	return {
    restrict: 'AE',
    replace: true,
    template: '<p style="background-color:{{color}}">Hello World',
    /*link函数*/
    link: function(scope, elem, attrs) {
      elem.bind('click', function() {
        elem.css('background-color','green');
        scope.$apply(function() {
          scope.color = "green";
        });
      });
      elem.bind('mouseover', function() {
        elem.css('cursor', 'pointer');
      });
    }
  };
});
</script>
</head>
<body>
	<input type="text" ng-model="color" placeholder="Enter a color" />
	<hello-World/>	
</body>
</html>


      运行效果图和对应html:

        
      我们注意到指令定义中的 link 函数。 它有三个参数:
      scope – 指令的scope。在我们的例子中,指令的scope就是父controller的scope。
      elem – 指令的jQLite(jQuery的子集)包装DOM元素。如果你在引入AngularJS之前引入了jQuery,那么这个元素就是jQuery元素,而不是jQLite元素。由于这个元素已经被jQuery/jQLite包装了,所以我们就在进行DOM操作的时候就不需要再使用 $()来进行包装。
       attr – 一个包含了指令所在元素的属性的标准化的参数对象。举个例子,你给一个HTML元素添加了一些属性:,那么可以在 link 函数中通过 attrs.someAttribute 来使用它。


       link函数主要用来为DOM元素添加事件监听、监视模型属性变化、以及更新DOM。在上面的指令代码片段中,我们添加了两个事件, click,和 mouseover。click 处理函数用来重置 <p> 的背景色,而 mouseover 处理函数改变鼠标为 pointer。在模板中有一个表达式 {{color}},当父scope中的 color 发生变化时,它用来改变 Hello World 文字的背景色。

      

       2、compile函数

       compile 函数在 link 函数被执行之前用来做一些DOM改造。它接收下面的参数:

       tElement – 指令所在的元素
       attrs – 元素上赋予的参数的标准化列表


      要注意的是 compile 函数不能访问 scope,并且必须返回一个 link 函数。但是如果没有设置 compile 函数,你可以正常地配置 link 函数,(有了compile,就不能用link,link函数由compile返回)。compile函数可以写成如下的形式:

app.directive('test', function() {
  return {
    compile: function(tElem,attrs) {
      
      //do optional DOM transformation here
      return function(scope,elem,attrs) {
        
      //linking function here
      };
    }
  };
});


      大多数的情况下,你只需要使用 link 函数。这是因为大部分的指令只需要考虑注册事件监听、监视模型、以及更新DOM等,这些都可以在 link 函数中完成。 但是对于像 ng-repeat 之类的指令,需要克隆和重复 DOM 元素多次,在 link 函数执行之前由 compile 函数来完成。

      3、指令执行过程

       整个指令的执行过程就分为:加载阶段-->编译阶段-->链接阶段。      


                 【AngularJS】——核心特性之指令の执行机制_第1张图片


       当应用引导启动的时候,Angular开始使用 $compile 服务遍历DOM元素。这个服务基于注册过的指令在标记文本中搜索指令。一旦所有的指令都被识别后,Angular执行他们的 compile 方法。如前面所讲的,compile 方法返回一个 link 函数,被添加到稍后执行的 link 函数列表中。这被称为编译阶段。如果一个指令需要被克隆很多次(比如 ng-repeat),compile函数只在编译阶段被执行一次,复制这些模板,但是link 函数会针对每个被复制的实例被执行。所以分开处理,让我们在性能上有一定的提高。这也说明了为什么在 compile 函数中不能访问到scope对象。 在编译阶段之后,就开始了链接(linking)阶段。在这个阶段,所有收集的 link 函数将被一一执行。指令创造出来的模板会在正确的scope下被解析和处理,然后返回具有事件响应的真实的DOM节点。


      

你可能感兴趣的:(AngularJS,Directive,指令)