angular中的自定義指令(續)

今天,接著昨天的angular自定義指令說一下其中的其他屬性

1、priority[number]屬性,這個屬性是來規定自定義的指令的優先級的,當一個DOM元素上面有一個以上的指令的時候,就需要去比較指令的優先級了,優先級高的指令先執行。這個優先級就是用來在執行指令的compile函數前,先排序的,那么關于compile這個函數,我們會在下面仔細的說下。

2、terminal[boolean]屬性,該參數用來定義是否停止當前元素上比本指令優先級低的指令,如果值為true,就是正常情況,按照優先級高低的順序來執行,如果設置為false,就不會執行當前元素上比本指令優先級低的指令。

3、link[function]屬性,在上面的例子中,我們自定義的指令其實沒有多大意義,這只是一個最簡單的指令,有好多的屬性我們都沒有為他定義,所以沒有多大用途。比如這個link函數,它包括三個參數:scope、element、attrs。這個link函數主要是用來添加對DOM元素的事件監聽、監視模型屬性變化、以及更新DOM的。它里面三個參數:

一:scope參數,在我們沒有為指令定義scope屬性的時候,那么他代表的就是父controller的scope。

二:element參數,就是指令的jQLite(jQuery的子集)包裝DOM元素。如果你在引入AngularJS之前引入了jQuery,那么這個元素就是jQuery元素,而不是jQLite元素。由于這個元素已經被jQuery/jQLite包裝了,所以我們就在進行DOM操作的時候就不需要再使用 $()來進行包裝。

三:attrs參數,它包含了該指令所在元素的屬性的標準化參數對象。

4、scope[boolean or object]屬性,該屬性是用來定義指令的scope的范圍,默認情況下是false,也就是說該指令繼承了父controller的scope,可以隨意的使用父controller的scope里的屬性,但是這樣的話就會污染到父scope里的屬性,這樣是不可取的。所以我們可以讓scope取以下兩個值:true和{}。

當為true的時候,表示讓Angular給指令創建一個繼承于父scope的scope。

eg:

let myapp=angular.module('myapp',[])

myapp.controller('myctrl',['$scope',function($scope) {

? ? ? ? ?$scope.color='red';

}])

myapp.directive('hello',function() {

? ? ? ?return{

? ? ? ? ? ? ? ?restrict:'AECM',

? ? ? ? ? ? ? ?replace:true,

? ? ? ? ? ? ? ?template:'click me',

? ? ? ? ? ? ? ?scope:true,

? ? ? ? ? ? ? ?link:function(scope,elements,attrs) {

? ? ? ? ? ? ? ? ? ? ? ? ?elements.bind('click',function() {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? elements.css('background-color','blue');

? ? ? ? ? ? ? ? ? ? ? ? ?})

? ? ? ? ? ? ? ?}

? ? ? ? ?}

})

這里我們為父scope定義了一個color的屬性,并賦值為red,在hello指令的scope屬性中,我們給了true,所以angular就為這個指令創建了一個繼承于父scope的scope,然后在template屬性中,我們用{{}}使用了從父scope中繼承過來的color屬性,所以按鈕會是紅色的。


當為{}的時候,表示創建一個隔離的scope,不會繼承父scope的屬性。但是在有的時候我們也要需要訪問父scope里的屬性或者方法,那么我們應該怎么辦呢。angular早就為我們想到了這一點,有以下的三個辦法可以讓我們記性上面的操作:

一:使用@實現單向綁定,如果我們只給scope的這個{}值的話,那么上面代碼的按鈕的背景色將會是灰色的。

,而如果我們需要使用父scope的color屬性的時候,我們可以這樣寫:

eg:

scope{

? ? ? ? color:'@color'

}

<hello color="{{color}}"></hello>

這里有兩點需要注意:1、scope里的屬性color代表的是模板{{}}這個表達式里面的color,兩者必須一致。2、scope里的屬性color的值,也就是@后面的color,表示的是下面的HTML元素里的屬性color,所以這兩者也必須一致,當這里的屬性名和模板里表達式{{}}里面使用的名稱相同的話,就可以省略掉@后面的屬性名了,然后寫成下面的形式。

scope{

? ? ? ?color:'@'

}

從指令中scope的值可以看出,指令模板中的表達式{{}}里的color的指向的是當前元素元素的color屬性,這個color屬性的值就是父scope的屬性color的值。父scope把他的color屬性值傳遞給了當前元素的color屬性,然后color屬性又把值傳遞給了模板中表達式里的color,這個過程是單向的。

二:使用=實現雙向綁定

myapp.directive('hello',function() {

? ? ? ?return{

? ? ? ? ? ? ? ?restrict:'AECM',

? ? ? ? ? ? ? ?replace:true,

? ? ? ? ? ? ? ?template:'click me',

? ? ? ? ? ? ? ?scope:{

? ? ? ? ? ? ? ? ? ? ?color:'='

? ? ? ? ? ? ? ?},

? ? ? ? ? ? ? ?link:function(scope,elements,attrs) {

? ? ? ? ? ? ? ? ? ? ? ? elements.bind('click',function() {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? elements.css('background-color','blue');

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? scope.$apply(function() {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? scope.color='pink';

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? })

? ? ? ? ? ? ? ? ? ? ? ? })

? ? ? ? ? ? ? ? ?}

? ? ? ? ? }

})

<hello color="{{color}}"></hello>

<input type="text" ng-model="color"/>

這里我們給指令的scope中的color屬性和父scope中的color屬性進行了雙向綁定,并且給指令的link函數里,添加了一個單擊事件,點擊按鈕會讓按鈕的顏色發生變化,并且改變指令scope的color屬性的值,再給HTML頁面中加了一個input標簽,輸出或者輸入父scope的color屬性的值。這里有一個地方需要注意:當前元素的屬性名的值不用再加上{{}}這個表達式了,因為這里父scope傳遞的是一個真實的scope數據模型,而不是簡單的字符串,所以這樣我們就可以傳遞簡單的字符串、數組、甚至復雜的對象給指令的scope。現在讓我們來看看點擊這個按鈕將會發生什么。

這里我們能看到,按鈕的顏色變成了粉色的,說明點擊讓指令的scope的color屬性發生了變化,從而導致按鈕的顏色發生了變化。但是這里不僅僅是按鈕發生了變化,注意看,input表單里的值也變成了pink,這就說明父scope的color屬性也發生了變化。 另外,再讓我們來給input里面輸入一個顏色,看看發生什么變化。

,可以看出當我們在表單里輸入另外一種顏色的時候,按鈕的顏色也發生了變化,這就說明指令的scope的color屬性被改變了。綜上我們可以發現使用'='實現的是雙向綁定。

三:使用&調用父scope里的方法

let myapp=angular.module('myapp',[])

myapp.controller('myctrl',['$scope',function($scope) {

? ? ? ?$scope.color='red';

? ? ? ?$scope.sayhello=function() {

? ? ? ? ? ? ?alert('hello');

? ? ? ?};

}])

myapp.directive('hello',function() {

? ? ? ?return{

? ? ? ? ? ? ?restrict:'AECM',

? ? ? ? ? ? ?replace:true,

? ? ? ? ? ? ?template:'click me',

? ? ? ? ? ? ?scope:{

? ? ? ? ? ? ? ? ? ? ?color:'=',

? ? ? ? ? ? ? ? ? ? ?sayhello:'&'

? ? ? ? ? ? ?},

? ? ? ? ? ? ?link:function(scope,elements,attrs) {

? ? ? ? ? ? ? ? ? ? ? elements.bind('click',function() {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?elements.css('background-color','blue');

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?scope.$apply(function() {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?scope.color='pink';

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?})

? ? ? ? ? ? ? ? ? ? ? ?})

? ? ? ? ? ? ? ? }

? ? ? ? }

})

這里我們也有兩個地方需要注意:1、我們不僅需要在模板中使用ng-click指令,綁定上要調用的父scope中的方法,而且要在給當前元素添加一個屬性,并且這個屬性指向要調用的父scope的方法。2、指令scope的屬性sayhello、當前元素的屬性sayhello、模板綁定的事件方法名sayhello這三者要一致。那么這樣我們就可以點擊按鈕,彈出一個對話框了。

5、compile[function]參數,該方法有兩個參數element,attrs,第一個參數element指指令所在的元素,第二個attrs指元素上賦予的參數的標準化列表。這里我們也有個地方需要注意:compile 函數不能訪問 scope,并且必須返回一個 link 函數。但是如果沒有設置 compile 函數,你可以正常地配置 link 函數,(有了compile,就不能用link,link函數由compile返回)。

myapp.directive('hello',function() {

? ? ? return{

? ? ? ? ? restrict:'AECM',

? ? ? ? ? replace:true,

? ? ? ? ? translude:true,

? ? ? ? ? template:'click me',

? ? ? ? ? scope:{

? ? ? ? ? ? ? ?color:'=',

? ? ? ? ? ? ? ?sayhello:'&'

? ? ? ? ?},

? ? ? ? ?compile:function(element,attrs) {

? ? ? ? ? ? ?returnfunction(scope,elements,attrs) {

? ? ? ? ? ? ? ? ?elements.bind('click',function() {

? ? ? ? ? ? ? ? ? ? ?elements.css('background-color','blue');

? ? ? ? ? ? ? ? ? ? ?scope.$apply(function() {

? ? ? ? ? ? ? ? ? ? ? ? ? scope.color='pink';

? ? ? ? ? ? ? ? ? ? ?})

? ? ? ? ? ? ? ? ? })

? ? ? ? ? ? ? };

? ? ? ? ? }

? ? ? }

})

現在讓我們來點擊這個按鈕

我們發現,這里點擊按鈕之后發生的事情和前面用link屬性的一樣,這其實是沒有多少差別的。

其實在大多數的情況下,我們只需要使用 link 函數。這是因為大部分的指令只需要考慮注冊事件監聽、監視模型、以及更新DOM等,這些都可以在 link 函數中完成。 但是對于像 ng-repeat 之類的指令,需要克隆和重復 DOM 元素多次,在 link 函數執行之前由 compile 函數來完成。那么為什么我們需要兩個分開的函數來完成生成過程,為什么不能只使用一個?要回答好這個問題,我們需要理解指令在Angular中是如何被編譯的!

6、指令是如何被編譯的

當我們的angular應用引導啟動的時候,angular將會使用$compile服務遍歷DOM元素,在所有的指令都被識別之后,將會調用指令的compile方法,返回一個link函數,然后將這個link函數添加到稍后執行的 link 函數列表中,這個過程被稱為編譯階段。像ng-repeat這樣的指令,需要被重復克隆很多次,compile函數只在編譯階段被執行一次,并且復制這些模板,但是link 函數會針對每個被復制的實例被執行。所以分開處理,讓我們在性能上有一定的提高(這句話有點不太理解,我是從別的地方copy過來的。

7、controller[string or function]和require[string or string[]]參數,當我們想要允許其他的指令和你的指令發生交互時,我們就需要使用 controller 函數。當另一個指令想要交互時,它需要聲明它對你的指令 controller 實例的引用(require)。

myapp.directive('hello',function() {

? ? ? return{

? ? ? ? ? ?scope:{},

? ? ? ? ? ?require:'^he',

? ? ? ? ? ?compile:function(element,attrs) {

? ? ? ? ? ? ? ? returnfunction(scope,elements,attrs,cntIns) {

? ? ? ? ? ? ? ? ? ? ? cntIns.fn()

? ? ? ? ? ? ? ? };

? ? ? ? ? ?}

? ? ? }

})

myapp.directive('he',function() {

? ? ? ?return{

? ? ? ? ? ? ?restrict:'AE',

? ? ? ? ? ? ?scope:{},

? ? ? ? ? ? ?controller:function($scope, $compile, $http) {

? ? ? ? ? ? ? ? ? this.fn=function() {

? ? ? ? ? ? ? ? ? alert('hello');

? ? ? ? ? ? ?};

? ? ? ? ?}

? ? }

})

<he>

<hello color="color"sayhello="sayhello()"></hello>

</he>

當頁面加載完畢之后,會彈出一個對話框。

好了上面就是我這段時間學習angular,所了解到的指令的知識,就先寫到這里了。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評論 6 546
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,814評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,980評論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,779評論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,109評論 1 330
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,287評論 0 291
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,799評論 1 338
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,515評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,750評論 1 375
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,933評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,492評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,703評論 2 380

推薦閱讀更多精彩內容