本篇講解指令的scope屬性:css
scope屬性值能夠有三種:html
一.scope:falsegit
默認值,這種狀況下,指令的做用域就是指令元素當前所在的做用域.github
二.scope:truejson
建立一個繼承了父做用域的子做用域,這樣,指令能夠訪問到父做用域裏的值,父做用域的屬性值一旦被修改,子做用域裏相應的屬性值也會被修改,可是子做用域裏的屬性值修改,不會影響到父做用域裏的屬性值app
舉個栗子:函數
html:spa
<!DOCTYPE html> <html ng-app="dirAppModule"> <head> <title>20.7.4 指令-scope</title> <meta charset="utf-8"> <script src="../angular.js"></script> <script type="text/ng-template" id="text.html"> <div> <h3 style="background-color:{{color}}" ng-transclude></h3> </div> </script> <script src="script.js"></script> </head> <body> <div ng-controller="bgColor"> <p>父做用域的color值:{{color}}</p> <input ng-model="color" placeholder="請輸入顏色值"/> <br/> <cd-hello><span>code_bunny</span></cd-hello> </div> </body> </html>
js:rest
/*20.7.4 指令 */ var appModule = angular.module('dirAppModule', []); appModule.controller('bgColor', function ($scope) { }); appModule.directive('cdHello', function () { return { restrict: 'EAC', templateUrl: 'text.html', replace: true, transclude: 'element', scope: true, link: function (scope, ele, attrs, ctrl, trans) { ele.bind('click', function () { scope.$apply(function () { scope.color = '#C0DCC0' }) }); ele.bind('mouseover', function () { ele.css({'cursor': 'pointer'}) }); } } });
建立一個這樣的應用:輸入顏色值能夠改變指令元素的背景色,點擊指令元素,重置顏色值爲豆沙綠code
→點擊元素後
能夠看到,輸入顏色值,父做用域裏的color值改變,指令的scope裏的color值也會改變,可是指令的scope裏的color值改變,不會影響到父元素的color值.這就是scope爲true時指令的做用域.
三.scope:{}
scope屬性爲一個json對象,這種狀況下,爲指令建立一個獨立的做用域.這個做用域和父做用域沒有任何關係.
注意,不可以在這個對象中自定義屬性和值,好比scope:{name:'code_bunny'},想象中這樣定義就是給指令的獨立做用域中定義了一個name屬性,值爲'code_bunny',但這樣是不對的!這個json對象中,只能使用三種綁定策略.若是須要給這個獨立做用域添加某個屬性,應該在在link函數的scope參數下進行添加.
當這個獨立的scope須要和父scope進行通訊時,可使用三種綁定策略:
(一)@綁定
@綁定能讓獨立做用域訪問到父做用域裏綁定的屬性值,可是獨立做用域下的這個值被修改,不影響到父做用域.相似於scope:true,可是僅僅是綁定的屬性,而不是所有的屬性.
來個栗子:
html:
<!DOCTYPE html> <html ng-app="dirAppModule"> <head> <title>20.7(1)指令-scope</title> <meta charset="utf-8"> <script src="../angular.js"></script> <script type="text/ng-template" id="text.html"> <div> <h3 style="background-color:{{color}}" ng-transclude></h3> </div> </script> <script src="script.js"></script> </head> <body> <div ng-controller="bgColor"> <input ng-model="color" placeholder="請輸入顏色值"/> <br/> <cd-hello col-attr="{{color}}"><span>code_bunny</span></cd-hello> </div> </body> </html>
js:
/*20.7.1 指令 */ var appModule = angular.module('dirAppModule', []); appModule.controller('bgColor',function($scope){}); appModule.directive('cdHello',function(){ return { restrict:'EAC', templateUrl:'text.html', replace:true, transclude:'element', scope:{ color:'@colAttr' }, link:function(scope,ele,attrs,ctrl,trans){ ele.bind('click',function(){ scope.$apply(function(){ scope.color = '#C0DCC0'; }) }); ele.bind('mouseover',function(){ ele.css({'cursor':'pointer'}) }); } } });
→輸入pink→點擊元素
能夠看到,獨立做用域綁定父元素的color屬性後,父元素的color屬性修改,指令裏的color屬性也被修改了.可是獨立做用域下的color屬性被修改,不會影響到父元素.
注意在這段代碼裏,有這3個顏色:
1.color: 這個是父元素裏的color屬性名
2.col-attr: 這個是指令元素裏用於綁定而建立的一個元素的屬性名
3.color: 這個color是獨立做用域裏的一個屬性名
以上三個屬性名都是能夠本身取的,不須要保持一致.綁定的方法直接看代碼裏的顏色.
爲了看得更清楚,我把它單獨拎出來寫一下:
父做用域有一個屬性叫color: <input ng-model="color" placeholder="請輸入顏色值"/>
指令元素建立一個col-attr屬性,讓它等於"{{color}}" <cd-hello col-attr="{{color}}"><span>code_bunny</span></cd-hello>
指令的scope裏進行綁定:
scope:{
color:'@colAttr' }
而後在link函數裏就可使用scope.color屬性了.
有兩個須要注意的地方:
1.元素的屬性不能使用駝峯命名,由於html不能識別大小寫,只能使用'-',在js綁定時@後面改爲駝峯命名.
2.當2和3同名時,能夠簡寫,好比:
屬性名叫mycolor:<cd-hello mycolor="{{color}}"><span>code_bunny</span></cd-hello>
scope下的屬性名也叫mycolor: scope:{mycolor:'@mycolor'}
這種狀況下能夠簡寫成: scope:{mycolor:'@'}
(二)=綁定:
=綁定可以讓獨立做用域和父做用域之間的某個屬性徹底共享,不管是父做用域下這個屬性被修改仍是獨立做用域下這個屬性被修改,另外一個做用域下的這個屬性都會同步變化.
來個栗子:
<!DOCTYPE html> <html ng-app="dirAppModule"> <head> <title>20.7(2)指令-scope</title> <meta charset="utf-8"> <script src="../angular.js"></script> <script type="text/ng-template" id="text.html"> <div> <h3 style="color:{{text_color}};background-color:{{color}}" ng-transclude></h3> </div> </script> <script src="script.js"></script> </head> <body> <div ng-controller="bgColor"> <input ng-model="color" placeholder="請輸入顏色值"/> <br/> <cd-hello bg-color="color"><span>code_bunny</span></cd-hello> </div> </body> </html>
js:
/*20.7.2 指令 */ var appModule = angular.module('dirAppModule', []); appModule.controller('bgColor',function($scope){}); appModule.directive('cdHello',function(){ return { restrict:'EAC', templateUrl:'text.html', replace:true, transclude:'element', scope:{ color:'=bgColor' }, link:function(scope,ele,attrs,ctrl,trans){ ele.bind('click',function(){ scope.$apply(function(){ scope.color = '#C0DCC0' }) }); ele.bind('mouseover',function(){ ele.css({'cursor':'pointer'}) }); } } });
→輸入pink→點擊元素
能夠看到,和@綁定不一樣,當我點擊元素,改變了獨立做用域下的color屬性時,父做用域下的color屬性也被改變了.他們是徹底同步的.
和@綁定同樣.一樣有三個顏色,一樣2和3同名的時候能夠簡寫.這裏就再也不贅述了.
須要特別注意的一點是:@綁定是col-attr="{{color}}",而=綁定是bg-color="color".一個是"{{color}}",一個是"color".這個千萬不能混淆了
(三)&綁定:
&綁定使得獨立做用域能夠訪問父做用域裏的函數.
來個栗子:
html:
<!DOCTYPE html> <html ng-app="dirAppModule"> <head> <title>20.7(3)指令-scope</title> <meta charset="utf-8"> <script src="../angular.min.js"></script> <script type="text/ng-template" id="text.html"> <div> <h3 ng-transclude></h3> </div> </script> <script src="script.js"></script> </head> <body> <div ng-controller="sayHelloCode"> <hello sayhello="sayHello(name)"><span>code_bunny</span></hello> </div> </body> </html>
js:
/*20.7.3 指令 */ var appModule = angular.module('dirAppModule', []); appModule.controller('sayHelloCode',function($scope){ $scope.sayHello=function(a){alert('hello,'+a)} }); appModule.directive('hello',function(){ return { restrict:'EAC', replace:true, templateUrl:'text.html', transclude:'element', scope:{ sayHello:'&sayhello' }, link:function(scope,ele,attrs,ctrl,trans){ ele.bind('click',function(){ scope.sayHello({name:'code_bunny'}); }); ele.bind('mouseover',function(){ ele.css({'cursor':'pointer'}) }); } } });
當點擊指令元素的時候,執行sayHello()方法.這裏須要注意參數的傳入方法:
sayhello中有一個形參:
$scope.sayHello=function(a){alert('hello,'+a)}
在html中定義傳入的參數名字叫name
<hello sayhello="sayHello(name)"><span>code_bunny</span></hello>
在調用的時候傳入一個對象{name:'code_bunny'}:
scope.sayHello({name:'code_bunny'});
這樣,就能夠把'code_bunny'做爲a的實參傳入.
和上面兩種綁定同樣.一樣有三個顏色,一樣2和3同名的時候能夠簡寫.這裏就再也不贅述了.
須要注意的是,&綁定的時候,sayhello="sayHello()"綁定的方法是須要()的.
三種綁定方法就介紹完了,還有很重要的注意點:
在使用綁定策略的時候,都是經過指令元素的屬性來綁定的,須要注意的是,用做綁定的這個屬性名千萬不要和指令名自己相同,這有可能會形成錯誤,好比這樣:
<color color="{{mycolor}}"><color/>
指令的名字叫color, 用於綁定mycolor屬性值的屬性名也叫color,這樣就不太好.須要避免這種狀況的發生.
最後,這三種綁定策略是能夠用在同一個指令中的.好比下面這個栗子:
html:
<!DOCTYPE html> <html ng-app="dirAppModule"> <head> <title>20.7(5)指令-scope</title> <meta charset="utf-8"> <script src="../angular.js"></script> <script type="text/ng-template" id="text.html"> <div> <h3 style="color:{{textColor}};background-color:{{bgColor}}" ng-transclude></h3> </div> </script> <script src="script.js"></script> </head> <body> <div ng-controller="bgColor"> <input ng-model="bg_color" placeholder="請輸入顏色值"/> <input ng-model="text_color" placeholder="請輸入顏色值"/> <br/> <cd-hello col-attr="{{bg_color}}" text-color="text_color" say-hello="sayHello()"><span>code_bunny</span></cd-hello> </div> </body> </html>
js:
/*20.7.5 指令 */ var appModule = angular.module('dirAppModule', []); appModule.controller('bgColor', function ($scope) { $scope.sayHello=function(){alert('hello')} }); appModule.directive('cdHello', function () { return { restrict: 'EAC', templateUrl: 'text.html', replace: true, transclude: 'element', scope: { bgColor: '@colAttr', textColor: '=textColor', sayHello: '&' }, link: function (scope, ele, attrs, ctrl, trans) { ele.bind('click', function () { scope.$apply(function () { scope.sayHello(); scope.color = '#C0DCC0'; scope.textColor = '#ccc'; }) }); ele.bind('mouseover', function () { ele.css({'cursor': 'pointer'}) }); } } });
→輸入背景色爲pink,文字色爲green→點擊元素彈出hello後:
背景色使用@綁定,文字色使用=綁定,sayHello函數使用&綁定.因此,一個指令中能夠混合使用多個多種綁定策略.
完整代碼:https://github.com/OOP-Code-Bunny/angular/tree/master/OREILLY 20.7.1 指令.html - 20.7.5 指令 .html
https://github.com/OOP-Code-Bunny/angular/blob/master/OREILLY/script.js