AngularJS 指令Directives實踐指南(一)

指令(Directives)是所有AngularJS應用最重要的部分。儘管AngularJS已經提供了非常豐富的指令,但還是經常需要創建應用特定的指令。這篇教程會爲你講述如何自定義指令,以及介紹如何在實際項目中使用。在這篇文章的最後(第二部分),我會指導你如何使用Angular指令來創建一個簡單的記事本應用。

概述

創建自定義指令:

一個Angular指令可以有以下的四種表現形式: 1. 一個新的HTML元素(<data-picker></data-picker>) 2. 元素的屬性(<input type=”text” data-picker/>) 3. CSS class(<input type=”text” class=”data-picker”/>) 4. 註釋(<!–directive:data-picker –>) 當然,我們可以控制我們的指令在HTML中的表現形式。下面我們來看一下AngularJS中的一個典型的指令的寫法。指令註冊的方式與 controller 一樣,但是它返回的是一個擁有指令配置屬性的簡單對象(指令定義對象) 。下面的代碼是一個簡單的 Hello World 指令。

var app = angular.module('myapp', []);
 
app.directive('helloWorld', function() {
  return {
      restrict: 'AE',
      replace: 'true',
      template: '<h3>Hello World!!</h3>'
  };
});

在上面的代碼中,app.directive()方法在模塊中註冊了一個新的指令。這個方法的第一個參數是這個指令的名字。第二個參數是一個返回指令定義對象的函數。如果你的指令依賴於其他的對象或者服務,比如 $rootScope, $http, 或者$compile,他們可以在這個時間被注入。這個指令在HTML中以一個元素使用,如下:

<hello-world/>
//OR
<hello:world/>

或者,以一個屬性的方式使用

<div hello-world></div>
//OR
<div hello:world/>

如果你想要符合HTML5的規範,你可以在元素前面添加 x- 或者 data-的前綴。所以下面的標記也會匹配 helloWorld 指令:

<div data-hello-world></div>
//OR
<div x-hello-world></div>

注意: 在匹配指令的時候,Angular會在元素或者屬性的名字中剔除 x- 或者 data- 前綴。 然後將 – 或者 : 連接的字符串轉換成駝峯(camelCase)表現形式,然後再與註冊過的指令進行匹配。這是爲什麼,我們在HTML中以 hello-world 的方式使用 helloWorld 指令。其實,這跟HTML對標籤和屬性不區分大小寫有關。 儘管上面的指令僅僅實現了靜態文字的顯示,但是這裏還是有一些有趣的點值得我們去挖掘。我們在指令定義過程中使用了三個屬性來配置指令。我們來一一介紹他們的作用。

  • restrict – 這個屬性用來指定指令在HTML中如何使用(還記得之前說的,指令的四種表示方式嗎)。在上面的例子中,我們使用了 ‘AE’。所以這個指令可以被當作新的HTML元素或者屬性來使用。如果要允許指令被當作class來使用,我們將 restrict 設置成 ‘AEC’。

  • template – 這個屬性規定了指令被Angular編譯和鏈接(link)後生成的HTML標記。這個屬性值不一定要是簡單的字符串。template 可以非常複雜,而且經常包含其他的指令,以及表達式(` `)等。更多的情況下你可能會見到 templateUrl, 而不是 template。所以,理想情況下,你應該將模板放到一個特定的HTML文件中,然後將 templateUrl 屬性指向它。

  • replace – 這個屬性指明生成的HTML內容是否會替換掉定義此指令的HTML元素。在我們的例子中,我們用 <hello-world></hello-world>的方式使用我們的指令,並且將 replace 設置成 true。所以,在指令被編譯之後,生成的模板內容替換掉了 <hello-world></hello-world>。最終的輸出是 <h3>Hello World!!</h3>。如果你將 replace 設置成 false,也就是默認值,那麼生成的模板會被插入到定義指令的元素中。

打開這個 plunker,在”Hello World!!”右鍵檢查元素內容,來更形象地明白這些。

Link函數和Scope

指令生成出的模板其實沒有太多意義,除非它在特定的scope下編譯。默認情況下,指令並不會創建新的子scope。更多的,它使用父scope。也就是說,如果指令存在於一個controller下,它就會使用這個controller的scope。 如何運用scope,我們要用到一個叫做 link 的函數。它由指令定義對象中的link屬性配置。讓我們來改變一下我們的 helloWorld 指令,當用戶在一個輸入框中輸入一種顏色的名稱時,Hello World 文字的背景色自動發生變化。同時,當用戶在 Hello World 文字上點擊時,背景色變回白色。 相應的HTML標記如下:

<body ng-controller="MainCtrl">
  <input type="text" ng-model="color" placeholder="Enter a color" />
  <hello-world/>
</body>

修改後的 helloWorld 指令如下:

app.directive('helloWorld', function() {
  return {
    restrict: 'AE',
    replace: true,
    template: '<p style="background-color:`color`">Hello World',
    link: function(scope, elem, attrs) {
      elem.bind('click', function() {
        elem.css('background-color', 'white');
        scope.$apply(function() {
          scope.color = "white";
        });
      });
      elem.bind('mouseover', function() {
        elem.css('cursor', 'pointer');
      });
    }
  };
});

我們注意到指令定義中的 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 文字的背景色。 這個 plunker 演示了這些概念。


原文鏈接: sitepoint   翻譯: 伯樂在線 陳 鑫偉
譯文鏈接: http://blog.jobbole.com/62249/

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章