【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、指令執行過程

       整個指令的執行過程就分爲:加載階段-->編譯階段-->鏈接階段。      


                 


       當應用引導啓動的時候,Angular開始使用 $compile 服務遍歷DOM元素。這個服務基於註冊過的指令在標記文本中搜索指令。一旦所有的指令都被識別後,Angular執行他們的 compile 方法。如前面所講的,compile 方法返回一個 link 函數,被添加到稍後執行的 link 函數列表中。這被稱爲編譯階段。如果一個指令需要被克隆很多次(比如 ng-repeat),compile函數只在編譯階段被執行一次,複製這些模板,但是link 函數會針對每個被複制的實例被執行。所以分開處理,讓我們在性能上有一定的提高。這也說明了爲什麼在 compile 函數中不能訪問到scope對象。 在編譯階段之後,就開始了鏈接(linking)階段。在這個階段,所有收集的 link 函數將被一一執行。指令創造出來的模板會在正確的scope下被解析和處理,然後返回具有事件響應的真實的DOM節點。


      

發佈了120 篇原創文章 · 獲贊 10 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章