[食譜好菜] AngularJS 的神兵利器之一 - Directive

[食譜好菜] AngularJS 基本術語及生命週期裡面有介紹到 Directive 主要分成兩種類型:行為的修飾詞(Modifier)、可重用的元件(Component),目的是給我們產生有意義的宣告,簡單來講就是實現抽象化,Directive 的使用者不需要也不必了解項目的運作方式,只要關注最終的結果就行了,我們來看一下如何建立 Directive?以及它有哪些基本的屬性?

建立一個簡單的 Directive

要使用 AngularJS 就從 NuGet 上安裝就可以了,下面這一段就是一個簡單的 Directive 應用情況。

my-directive 是我自己自建的 Directive,屬於可重用的元件類型,而它呈現的畫面長下面這樣,其中 我叫 軟體主廚 的部分就是 my-directive 定義的。

my-directive 裡面有一個 name 屬性,綁定了 indexCtrl.name 屬性,所以 my-directive name 的資料是從 indexCtrl.name 來的,而 my-directive 的程式碼長這樣。

angular.module("directive-module", []).directive("myDirective", function () {
    return {
        replace: true,
        restrict: "E",
        scope: {
            name: "="
        },
        template: "<div><h2>我叫 {{ name }}</h2></div>"
    };
});

看不懂?沒關係,我們就來看一下 Directive 有哪些基本的屬性?

Directive 的基本屬性

宣告 Directive 的基本起手式為:

angular.module("module name", [])
    .directive("directive name", function () {
        return {
            ...
        };
    });

Directive 必須定義在某個 module 底下,接著給 Directive 一個名稱,然後在 function () 內回傳一個 Directive object,並在 object 內填入屬性值。

restrict

restrict 大概是我們最先要決定的屬性值,restrict 用來定義 Directive 使用上的限制範圍,屬性值有 A E C M,說明如下:

  • A:指定 directive 可以做為 HTML 的屬性(attribute)。
  • E:指定 directive 可以做為一個 HTML 元素,意思就是我們可把 directive 做成 HTML 標籤,就如同上面的範例一樣。
  • C:指定 directive 可以做為一個 class 的名稱。
  • M:指定 directive 可以做為 HTML 的註解。

以上四種我們平常比較常用到的是 A、E,而 AECM 不是只能單獨指定而已,我們還可以指定多個,另外,restrict 如果不指定的話,預設值是 A。

replace

replace 預設值為 false,當設為 true 時 AngularJS 會用 template 或 templateUrl 的內容,來取代 directive 宣告的 HTML 元素,現在舉個例子來看看差異。

設為 false(預設值)

設為 true

template、templateUrl

template 是讓我們放置 HTML 模板的地方,用法就像最上面的範例那樣,除此之外,我們還可以將 HTML 模板另存成 .html 檔,然後在 templateUrl 屬性指定路徑,AngularJS 就會從我們指定的路徑將模板載入進來。

scope

directive 也是有 scope 的,預設 directive 是繼承父 scope,意思就是說我們可以在 link 函式內存取到父 scope 內的所有變數及函式。

scope 的屬性值可以設定為以下的值:

  • false:這是預設值,基本上 directive 預設的 scope 與父 scope 是一樣。
  • true:這個值表示 directive 還是繼承父 scope,但是會建立自己的 sub scope,讓來自父 scope 內的所有變數及函式得以在 link 函式內存取,但是在 link 函式內如果有修改到來自父 scope 的變數或函式,這個修改的動作則不會去影響到原本父 scope 的變數及函式。
  • object:我們可以指定 directive 的 scope 為一個 object,這個 object 會讓 directive 建立一個 isolated scope,這個 isolated scope 不會從父 scope 中繼承任何的變數及函式,完全就是獨立運作,如果需要父 scope 內的變數及函式,則透過 HTML 屬性來傳遞。

scope 我會建議就儘量建立 isolated scope,讓 directive 不要與父 scope 相依,我們拿最上面的範例來看,scope 就是一個 object,裡面宣告了一個 name 屬性,值是 "=",我們來看一下這是什麼意思?

當 scope 指定為一個 object 時,屬性就可以拿來做資料綁定,因此它會出現在模板裡面。

除此之外,屬性名稱也會被當做是 HTML 屬性的名稱,所以 name 會在 <my-directive> 中出現。

scope object 的屬性值可以設定的值有下列三種:

  • "=":代表在 HTML 內的屬性值是一個物件(或變數),將這個物件(或變數)指定給 scope object 的屬性。
  • "@":代表在 HTML 內的屬性值是一個純字串,指定後我們從 scope object 的屬性取到的值,就會是在 HTML 內的屬性上出現的字串。
  • "&":代表在 HTML 內的屬性值是一個函式,指定後我們就可以直接從 scope object 的屬性去呼叫。

我修改一下原本的範例,來看一下 "=" 除外的 "@" 與 "&" 的不同。

"@"

"&"

link

最後一個要介紹的 Directive 基本屬性是 link 函式,link 函式的主要工作是用來操作 directive 的 DOM 以及定義必要的 APIs 及函式,link 函式內常會用到的 3 個參數分別是:

  • scope:這個就是 directive 的 scope,我們可以利用這個參數再額外定義可以綁定的變數及函式。
  • element:這個是 AngularJS 用 jqLite 所包裝出來的一個 DOM 物件,我們可以透過這個物件來操作 directive 所渲染出來的 DOM。
  • attrs:這個是 directive 上的所有 HTML 屬性集合而成的 hash object,我們可以透過 attrs 取得這些屬性所被賦予的值,但是要注意的是,取得到的值都是純字串。

下面我修改了一下原本的範例,簡單呈現這 3 個參數的運用狀況。

參考資料

 < Source Code >

相關資源

C# 指南
ASP.NET 教學
ASP.NET MVC 指引
Azure SQL Database 教學
SQL Server 教學
Xamarin.Forms 教學