建立自訂 AngularJS 指令:Part 4 transclude和restrict介紹
在本系列的第3篇文章中,我介紹了指令中定義的孤立範圍屬性怎樣傳遞參數給外部函數(初看起來需要一些技巧,一旦掌握要點就變得很簡單了)。在這篇文章中,我將將繼續介紹相關自訂指令的知識,主要介紹transclude和restrict這兩個指令參數,看看它們有什麼功能,以及怎樣使用。
指令中的restrict
在HTML中,指令可以被定義為元素、屬性、CSS類、注釋。你怎樣限定你的自訂指令使用方式呢?
可以使用restrict介面屬性來規定自訂指令在HTML中怎麼使用、在哪使用。這個介面屬性的值有下邊幾種:
| restrict的值 |
解釋 |
| E |
當做元素使用。樣本: |
| A |
當做元素屬性使用。樣本: |
| C |
當做元素上的樣式類使用。樣本: |
| M |
當做注釋使用(很少使用)。樣本: |
下邊是一個指令用作元素或屬性的例子。注意,這兩個值之間沒有被隔開。
app.directive('myDirectiveWithRestriction', function () { return { restrict: 'EA', scope: { tasks: '=' } };});
即使C和M值也可以使用,但很少用到。大多數指令只使用E和A。現在,你已經瞭解了restrict,下邊讓我們看transclude的概念。
指令中的transclude
我第一次聽到這個詞“transclusion”,我懷疑它是不是一個真正的單詞(如果你已經在YouTube上看到我在AngularJS分鐘60ish視頻,你就會知道這是真的)。如果你在一個網路字典中尋找這個單詞,你不會找到任何東西,但定義可以在維基百科等網站上找到。大多數的網站定義“transclusion”以下列方式:
通過引用的方式包含文檔或文檔的一部分到另一個文檔(見維基百科)。
如果你曾經載入CSS樣式表或HTML模板(HTML5更新的功能)到HTML頁面或載入的頁首或頁尾的HTML片段到伺服器端頁面(通常稱為伺服器端包括),那麼你已經使用transclusion的方法了。這裡有一個簡短的視頻,提供transclusion的快速概覽:(視頻見原文)
對於AngularJS來說,transclude(transclusion 的動詞形式)提供了一種定義插入指令的模板和展示這個模板的方法。例如:你可能會有一個需要輸出一個表格的指令,並且允許使用指令的人控制怎樣渲染表格行。或者,你可能會有一個輸出一條錯誤資訊的指令,並且指令的使用者可以控制HTML內容和使用不同渲染顏色。通過這些類型的功能,指令使用者可以有更多的控制權,去控制指令產生的HTML各個部分如何渲染。
要支援替換,有兩個要點必須掌握。第一個要點是使用
transclude屬性在指令中,在HTML中,自訂指令內部還有其它DOM時,如果
transclude屬性設定為false,指令內定義的模板將會替換掉指令內部的DOM;如果
transclude屬性設定為false,將會把這些DOM放到指令內部模板中
ng-transclude指令所在的地方,如果沒有寫
ng-transclude,這些DOM也將不會出現在頁面中。第二個要點是
ng-transclude指令,它是AngularJS內部指令,它被用來決定在一個指令模板中哪個地方嵌入外部內容。下邊的指令代碼,使用這兩個要點實現替換。
原始的內容,
還會在這裡。 <script src=../../lib/angular.js></script><script src=../../lib/jquery.js></script><script> var app = angular.module('directivesModule', []); app.directive('hello', function() { return { restrict: 'E', template: 'Hi there ', transclude: true, replace:false }; });</script>
運行效果如下:
Hi there
原始的內容,
還會在這裡。 Hi there
在這個例子中,還可以看到有個replace屬性,當這個屬性設定為true時,將會使用模板替換掉頁面中標籤所在的DOM(樣本中的hello標籤);設定為false時,將會把模板放到標籤內部。
總結
一旦你理解了transclude的使用方法,它將會變得很簡單。就像視頻中提到的,伺服器端包含或者CSS樣式單嵌入網頁的概念與transclude類似。在指令中使用transclude 和ng-transclude,你可以使你的指令具有定製功能。
到這裡,自訂指令系列是否結束了?不幸的是,沒有結束。當指令模板中包含ng-repeat 或ng-if 時,transclude將會變得很複雜。我將會在接下來的文章中介紹如何處理這些情境。