一個指令被創建后,你是希望它繼承父類作用域,還是自己獨創個獨立作用域,還是一部分繼承父類的,然后加上自己獨創的呢?
幸好angularjs在指令中可以讓我們自己配置我們自己想要的情況:
app.directive("myDirective", function () {
var obj = {
//J4 指令的聲明模式為 "AE" 屬性和元素
restrict: "AE",
//J5 指令繼承父作用域的屬性和方法
scope: false,
replace: true,
template: ""
}
return obj;
});
上面的代碼是一個簡潔的angualr指令代碼,其中obj對象中有scope屬性,其值有三種情況,默認為false。
scope: false
????scope的值為false,表明此指令沒有創建自己的scope作用域,它使用了父類的作用域,因此指令和它的父類都使用了同一個作用域,此時修改指令的數據,會立即反應到父類上,同時,修改父類的同名數據也會立即反應到子指令上,因此,scope:false 數據是雙向綁定的。
????這里要注意一個細節:如果scope:false。說明指令和父類公用一個scope。angularjs會把指令中和父類中的ng-model、ng-bind和{{}}等不管name是否相同都會綁定一個$watch,并且push到公用scope$$watchers數組中。這樣,當數據發生變動的時候,都會執行$digest方法來對$$watchers數組進行遍歷更新新值,從而實現了數據的雙向綁定。這也是angularjs實現數據雙向綁定的原理。-
scope: true
????scope的值為true,表明此指令創建了自己的scope。但是它這個scope繼承了父類scope上的所有數據。這里的繼承是javascript的原型鏈繼承方式。因此指令的scope是父類scope的子scope。scope.png
????相當于借用了父類的數據進行了模型的初始化。比如父類有個ng-model=“name”,初始值為name=“你好”。指令中也有一個ng-model="name",此時它的值應該就是“你好”(沒有在自己的scope中定義name的情況下),當然如果子類的scope已經定義了name,就不會去尋找父類scope的name,這和原型鏈繼承是一樣的。
????等等,那么,我改變了父scope的數據,子scope的相應數據是怎么改變的呢?其實,這里有個細節需要知道:就是每次父scope數據變化的時候,它會執行scope.$digest(),當$digest循環發生的時候,它會遍歷當前$scope及其所有子$scope上已注冊的所有watchers函數。
????這就是說,當父scope.name發生變化,scope.$digest()執行,所以父頁面name變化了。同時子scope.$digest(),執行,而子scope.name是繼承父scope.name,所以子頁面name也變化了。同時name值是一樣的,這樣就實現了父到子的單項綁定。 scope: {}
????當我們將scope設置為{}時,意味著我們創建的一個新的與父作用域隔離的新的作用域,這使我們在不知道外部環境的情況下,就可以正常工作,不依賴外部環境,而且連繼承都沒有。
????那問題來了,那我想和我的父類交互比如數據怎么辦呢?幸好angularjs提供了一些方法,@,=,&。
3.1 @
????這是一個單項綁定的前綴標識符。使用方法:在元素中使用屬性,好比這樣<div my-directive my-name="{{name}}"></div>,注意,屬性的名字要用-將兩個單詞連接,因為是數據的單項綁定所以要通過使用{{}}來綁定數據。父scope的數據變化會更新子scope的數據,也就是單項綁定。這個與之前scope:true所說的原型繼承是不同的,區別如下:
????首先,原型繼承,是先判斷自己scope是否有相應的模型,如果有則使用,如果沒有則使用原型繼承。單項綁定是父scope數據變化后執行了scope和子scope的$digest來完成父scope到子scope的數據更新。
????@name的作用是父scope.name變化,子scope.name就跟著變化。當父scope.name變化時,會執行父scope.$digest和子scope.$digest。因此父子同時變化,實現單項綁定。
3.2 =
????這是一個雙向數據綁定前綴標識符使用方法:在元素中使用屬性,好比這樣<div my-directive age="age"></div>,注意,數據的雙向綁定要通過=前綴標識符實現,所以不可以使用{{}}。
????=name的作用是數據雙向變化,父scope.name變化,子scope.name跟著變化。子scope.name變化,父scope.name也跟著變化。父scope.name變化,scope.$digest和子scope.$digest執行,實現父到子的單項綁定。子scope.name變化,會自動執行scope.$applay()方法然后會自動地調用$rootScope.$digest(),這樣整個頁面綁定的$watch都執行了一遍,所以父scope.name也更新了,實現了子scope.name到父scope.name的單項綁定。最終實現了數據雙向綁定。
3.3 &