文章是轉的,我做下補充。原文地址:https://segmentfault.com/a/1190000002773689
每當一個指令被創建的時候,都會有這樣一個選擇,是繼承自己的父作用域(一般是外部的Controller提供的作用域或者根作用域($rootScope)),還是創建一個新的自己的作用域,當然AngularJS為我們指令的scope
參數提供了三種選擇,分別是:false
,true
,{}
;默認情況下是false
。
scope = false
首先我們來看一下,當scope
參數被設置為false
時有什么情況發生
在這種情況下,在指令模板中可以直接使用父作用域中的變量,函數
首先我們來創建一個指令,代碼如下所示:
http://codepen.io/mafeifan/pen/kXORKN?editors=1010
下面我們來詳細解釋一下上面的代碼:
因為我們將scope
的屬性設置為false
所以,我們創建的指令繼承了父作用域的一切屬性和方法,這也使得在指令的模板中我們可以使用這些屬性和方法。
注意:此時我們在輸入框里改變名字,會發現上面的兩個名字都發生了變化,你肯定會說,這肯定是這樣啊,數據綁定嘛,好,我們接着往下走。
scope = true
當把scope
屬性設置為true
時,這表明我們創建的指令要創建一個新的作用域,這個作用域繼承自我們的父作用域。
等等,剛才我們不是說了,當把scope
屬性值設置為false
時,不也是繼承我們的父作用域嗎?表急,我們接着往下看。
修改上面的JS代碼,將指令中的:
scope:false
修改為scope:true
然后我們再試着在我們的input
輸入框中寫一些字符串,會發現,指令中的那個name
發生了變化,但是指令外的那個name
卻沒有發生變化,這說明了一個問題。
- 當我們將
scope
設置為true
的時候,我們就新創建了一個作用域,只不過這個作用域是繼承了我們的父作用域;我覺得可以這樣理解,我們新創建的作用域是一個新的作用域,只不過在初始化的時候,用了父作用域的屬性和方法去填充我們這個新的作用域。它和父作用域不是同一個作用域。 - 當我們將
scope
設置為false
的時候,我們創建的指令和父作用域(其實是同一個作用域)共享同一個model
模型,所以在指令中修改模型數據,它會反映到父作用域的模型中。
http://codepen.io/mafeifan/pen/WxVgqL?editors=1010
scope = {}
下面我們要進入一個好玩的部分,當我們將scope
的屬性設置為{}
時,我們可以做更多的事情。
AngularJS最強的大的地方之一就是它可以構建組建,無論放在哪里都是可以使用的;
這所以可以做到這些,不得不歸功於指令的這個屬性;當我們將scope
設置為{}
時,意味着我們創建的一個新的與父作用域隔離的新的作用域,這使我們在不知道外部環境的情況下,就可以正常工作,不依賴外部環境。
當然首先我們還是要給出我們的例子,先看代碼,我們修改了上述的JS代碼和HTML代碼
代碼:
http://codepen.io/mafeifan/pen/EyraKX?editors=1010
我們使用了隔離的作用域,不代表我們不可以使用父作用域的屬性和方法。
- 我們可以通過向
scope
的{}
中傳入特殊的前綴標識符(即prefix
),來進行數據的綁定。 - 在創建了隔離的作用域,我們可以通過
@
,&
,=
引用應用指令的元素的屬性,如上面的代碼那樣,我們可以在<div class="my-directive" my-directive my-name="{{name}}" age="age" change-my-age="changeAge()"></div>
這個元素中,利用前綴標識符通過使用屬性my-name
,age
,change-my-age
來引用這些屬性的值。
下面我們來看看如何使用這些前綴標識符:
@
單項綁定的前綴標識符
使用方法:在元素中使用屬性,好比這樣<div my-directive my-name="{{name}}"></div>
,注意,屬性的名字要用-
將兩個單詞連接,因為是數據的單項綁定所以要通過使用{{}}
來綁定數據。
=
雙向數據綁定前綴標識符
使用方法:在元素中使用屬性,好比這樣<div my-directive age="age"></div>
,注意,數據的雙向綁定要通過=
前綴標識符實現,所以不可以使用{{}}
。
<
單項綁定的前綴標識符,和=使用類似。不同的是改變內部scope不會反映到parent的scope
使用方法:在元素中使用屬性,好比這樣<my-component my-attr="parentModel">,directive的定義scope: { localModel:'<myAttr' }。代碼
&
綁定函數方法的前綴標識符
使用方法:在元素中使用屬性,好比這樣<div my-directive change-my-age="changeAge()"></div>
,注意,屬性的名字要用-
將多個個單詞連接。
注意:在新創建指令的作用域對象中,使用屬性的名字進行綁定時,要使用駝峰命名標准,比如下面的代碼。
scope: { // `myName` 就是原來元素中的`my-name`屬性 name: '@myName', age: '=', // `changeMyAge`就是原來元素中的`change-my-age`屬性 changeAge: '&changeMyAge' }
進一步說明,我們的指令是如何利用這些前綴標識符來尋找我們想要的屬性或者函數的?
@
當指令編譯到模板的name
時,就會到scope
中尋找是否含有name
的鍵值對,如果存在,就像上面那樣,看到@
就知道這是一個單向的數據綁定,然后尋找原來的那個使用指令的元素上(或者是指令元素本身)含有這個值的屬性即my-name={{name}}
,然后在父作用域查找{{name}}
的值,得到之后傳遞給模板中的name
。=
和&
與@
差不多,只不過=
進行的是雙向的數據綁定,不論模板還是父作用域上的屬性的值發生改變都會使另一個值發生改變,而&
是綁定函數而已。