angular.module("app",[]).directive("directiveName",function(){
return{
//通過(guò)設(shè)置項(xiàng)來(lái)定義
};
})
return返回的對(duì)象包含很多參數(shù),下面一一說(shuō)明

- restrict
可選參數(shù),指明指令在DOM里面以什么形式被聲明
取值有:E(元素),A(屬性),C(類),M(注釋),其中默認(rèn)值為A;
E(元素):<directiveName></directiveName>
A(屬性):<div directiveName='expression'></div>
C(類): <div class='directiveName'></div>
M(注釋):<--directive:directiveName expression-->
例如restrict:‘EA’ 則表示指令在DOM里面可用元素形式和屬性形式被聲明;
一般來(lái)說(shuō),當(dāng)你創(chuàng)建一個(gè)有自己模板的組件的時(shí)候,需要使用元素名,如果僅僅是為為已有元素添加功能的話,就使用屬性名。
注意:如果想支持IE8,則最好使用屬性和類形式來(lái)定義。 另外Angular從1.3.x開(kāi)始, 已經(jīng)放棄支持IE8了.
- priority
(數(shù)字),可選參數(shù),指明指令的優(yōu)先級(jí),若在單個(gè)DOM上有多個(gè)指令,則優(yōu)先級(jí)高的先執(zhí)行;
設(shè)置指令的優(yōu)先級(jí)算是不常用的。
比較特殊的的例子是,angularjs內(nèi)置指令的ng-repeat的優(yōu)先級(jí)為1000,ng-init的優(yōu)先級(jí)為450; - terminal
(布爾型),可選參數(shù),可以被設(shè)置為true或false,若設(shè)置為true,則優(yōu)先級(jí)低于此指令的其他指令則無(wú)效,不會(huì)被調(diào)用(優(yōu)先級(jí)相同的還是會(huì)執(zhí)行) - template(字符串或者函數(shù))可選參數(shù),可以是:
(1) 一段HTML文本
angular.module("app",[]).directive("hello",function(){
return{
restrict:'EA',
template:"<div><h3>hello world</h3></div>"
};
})
html代碼:<hello></hello>
結(jié)果渲染后的HTML為:
<hello>
<div><h3>hello world</h3></div>
</hello>
(2) 一個(gè)函數(shù),可接受兩個(gè)參數(shù)tElement和tAttrs
其中tElement是指使用此指令的元素,而tAttrs則實(shí)例的屬性,它是一個(gè)由元素上所有的屬性組成的集合(對(duì)象)形如:
{
title:‘a(chǎn)aaa’,
name:'leifeng'
}
下面讓我們看看template是一個(gè)函數(shù)時(shí)候的情況
angular.module("app",[]).directive("directitle",function(){
return{
restrict:'EAC',
template: function(tElement,tAttrs){
var _html = '';
_html += '<div>'+tAttrs.title+'</div>';
return _html;
}
};
})
HTML代碼:<directitle title='biaoti'></directitle>
渲染之后的HTML:<div>biaoti</div>
因?yàn)橐欢蜨TML文本,閱讀跟維護(hù)起來(lái)都是很麻煩的,所用通常會(huì)使用templateUrl這個(gè)。
- templateUrl(字符串或者函數(shù)),可選參數(shù),可以是
(1) 一個(gè)代表HTML文件路徑的字符串
(2) 一個(gè)函數(shù),可接受兩個(gè)參數(shù)tElement和tAttrs(大致同上)
注意:
在本地開(kāi)發(fā)時(shí)候,需要運(yùn)行一個(gè)服務(wù)器,不然使用templateUrl會(huì)報(bào)錯(cuò) Cross Origin Request Script(CORS)錯(cuò)誤;
由于加載html模板是通過(guò)異步加載的,若加載大量的模板會(huì)拖慢網(wǎng)站的速度,這里有個(gè)技巧,就是先緩存模板;
你可以再你的index頁(yè)面加載好的,將下列代碼作為你頁(yè)面的一部分包含在里面。
<script type='text/ng-template' id='woshimuban.html'>
<div>我是模板內(nèi)容</div>
</script>
這里的id屬性就是被設(shè)置在templateUrl上用的。
另一種辦法緩存是:
angular.module("template.html", []).run(["$templateCache", function($templateCache) {
$templateCache.put("template.html",
"<div>wo shi mu ban</div>");
}]);
- replace
(布爾值),默認(rèn)值為false,設(shè)置為true時(shí)候,我們?cè)賮?lái)看看下面的例子(對(duì)比下在template時(shí)候舉的例子)
angular.module("app",[]).directive("hello",function(){
return{
restrict:'EA',
replace:true,
template:"<div><h3>hello world</h3></div>"
};
})
HTML代碼為:
<hello></hello>
渲染之后的代碼:<div><h3>hello world</h3></div>
對(duì)比下沒(méi)有開(kāi)啟replace時(shí)候的渲染出來(lái)的HTML。發(fā)現(xiàn)<hello></hello>不見(jiàn)了。
另外當(dāng)模板為純文本(即template:"wo shi wen ben")的時(shí)候,渲染之后的html代碼默認(rèn)的為文本用span包含。
- scope
可選參數(shù),(布爾值或者對(duì)象(默認(rèn)值為false,可能取值:
(1) 默認(rèn)值false。
表示繼承父作用域;
(2) true
表示繼承父作用域,并創(chuàng)建自己的作用域(子作用域);
(3) {}
表示創(chuàng)建一個(gè)全新的隔離作用域; - 首先我們先來(lái)了解下scope的繼承機(jī)制。我們用ng-controller這個(gè)指令舉例。
我們都知道ng-controller(內(nèi)置指令)可以從父作用域中繼承并且創(chuàng)建一個(gè)新的子作用域。如下:
<!doctype html>
<html ng-app="myApp">
<head>
<script src="http://cdn.staticfile.org/angular.js/1.2.10/angular.min.js"></script>
</head>
<body>
<div ng-init="aaa='父親'">
parentNode:{{aaa}}
<div ng-controller="myController">
chrildNode: {{aaa}}
</div>
</div>
<script>
angular.module('myApp', [])
.controller('myController',function($scope){
$scope.aaa = '兒子'
})
</script>
</body>
</html>
這時(shí)頁(yè)面顯示是
parentNode:父親
chrildNode: 兒子
若去掉 $scope.aaa = '兒子'
則顯示
parentNode:父親
chrildNode: 父親
注意:
(1) 若一個(gè)元素上有多個(gè)指令,使用了隔離作用域,則只有其中一個(gè)可以生效;
(2) 只有指令模板中的根元素才能獲得一個(gè)新的作用域,這時(shí)候,scope就被設(shè)置為true了;
<!doctype html>
<html ng-app="myApp">
<head>
<script src="http://cdn.staticfile.org/angular.js/1.2.10/angular.min.js"></script>
</head>
<body>
<div ng-init="aaa='父親'">
parentNode:{{aaa}}
<div class='one' ng-controller="myController">
chrildNode: {{aaa}}
<div class='two' ng-controller='myController2'>
{{aaa}}
</div>
</div>
</div>
<script>
angular.module('myApp', [])
.controller('myController',function($scope){
$scope.aaa = '兒子';
})
.controller('myController2',function($scope){
$scope.aaa = '孫女';
})
</script>
</body>
</html>
頁(yè)面顯示為:
parentNode:父親
chrildNode: 二字
chrildNode: 孫女
上面中class為one那個(gè)div獲得了指令ng-controller=’myController‘所創(chuàng)建的新的作用域;
而class為two那個(gè)div獲得了指令ng-controller=’myController2‘所創(chuàng)建的新的作用域;
這就是“只有指令模板中的根元素才能獲得一個(gè)新的作用域”;
** 接下來(lái)我們通過(guò)一個(gè)簡(jiǎn)單明了的例子來(lái)說(shuō)明scope取值不同的差別 **
<!doctype html>
<html ng-app="myApp">
<head>
<script src="http://cdn.staticfile.org/angular.js/1.2.10/angular.min.js"></script>
</head>
<body>
<div ng-controller='MainController'>
父親: {{name}}
<input ng-model="name" />
<div my-directive></div>
</div>
<script>
angular.module('myApp', [])
.controller('MainController', function ($scope) {
$scope.name = 'leifeng';
})
.directive('myDirective', function () {
return {
restrict: 'EA',
scope:false,//改變此處的取值,看看有什么不同
template: '<div>兒子:{{ name }}<input ng-model="name"/></div>'
};
});
</script>
</body>
</html>
依次設(shè)置scope的值false,true,{},結(jié)果發(fā)現(xiàn):
當(dāng)為false時(shí)候,兒子繼承父親的值,改變父親的值,兒子的值也隨之變化,反之亦如此。(繼承不隔離)
當(dāng)為true時(shí)候,兒子繼承父親的值,改變父親的值,兒子的值隨之變化,但是改變兒子的值,父親的值不變。(繼承隔離)
當(dāng)為{}時(shí)候,沒(méi)有繼承父親的值,所以兒子的值為空,改變?nèi)魏我环降闹稻荒苡绊懥硪环降闹?。(不繼承隔離)
tip:
當(dāng)你想要?jiǎng)?chuàng)建一個(gè)可重用的組件時(shí)隔離作用域是一個(gè)很好的選擇,通過(guò)隔離作用域我們確保指令是‘獨(dú)立’的,并可以輕松地插入到任何HTML app中,并且這種做法防止了父作用域被污染;
- 隔離作用域可以通過(guò)綁定策略來(lái)訪問(wèn)父作用域的屬性。
下面看一個(gè)例子
<!doctype html>
<html ng-app="myApp">
<head>
<script src="http://cdn.staticfile.org/angular.js/1.2.10/angular.min.js"></script>
</head>
<body>
<div ng-controller='MainController'>
<input type="text" ng-model="color" placeholder="Enter a color"/>
<hello-world></hello-world>
</div>
<script>
var app = angular.module('myApp',[]);
app.controller('MainController',function(){});
app.directive('helloWorld',function(){
return {
scope: false,
restrict: 'AE',
replace: true,
template: '<p style="background-color:{{color}}">Hello World</p>'
}
});
</script>
</body>
</html>
運(yùn)行代碼,并在input中輸入顏色值,結(jié)果為

但是,但我們將scope設(shè)置為{}時(shí)候,再次運(yùn)行上面的代碼可以發(fā)現(xiàn)頁(yè)面并不能成功完整顯示!
原因在于,這里我們將scope設(shè)置為{},產(chǎn)生了隔離作用域。
所以在template模板中{{color}}變成了依賴于自己的作用域,而不是依賴于父作用域。
因此我們需要一些辦法來(lái)讓隔離作用域能讀取父作用域的屬性,就是綁定策略。
下面我們就來(lái)探索設(shè)置這種綁定的幾種方法
方法一:使用@(@attr)來(lái)進(jìn)行單向文本(字符串)綁定
<!doctype html>
<html ng-app="myApp">
<head>
<script src="http://cdn.staticfile.org/angular.js/1.2.10/angular.min.js"></script>
</head>
<body>
<div ng-controller='MainController'>
<input type="text" ng-model="color" placeholder="Enter a color"/>
<hello-world color-attr='{{color}}'></hello-world> //注意這里設(shè)置了color-attr屬性,綁定了{(lán){color}}
</div>
<script>
var app = angular.module('myApp',[]);
app.controller('MainController',function(){});
app.directive('helloWorld',function(){
return {
scope: {color:'@colorAttr'}, //指明了隔離作用域中的屬性color應(yīng)該綁定到屬性colorAttr
restrict: 'AE',
replace: true,
template: '<p style="background-color:{{color}}">Hello World</p>'
}
});
</script>
</body>
</html>
這種辦法只能單向,通過(guò)在運(yùn)行的指令的那個(gè)html標(biāo)簽上設(shè)置color-attr屬性,并且采用{{}}綁定某個(gè)模型值。
注意,你也可以再這里直接綁定字符串的顏色值,如:color-attr=“red”;
然后你可以看到表達(dá)式{{color}}被賦值給了color-attr。
當(dāng)表達(dá)式的值發(fā)生變化時(shí),屬性color-attr也會(huì)發(fā)生變化,所以也改變了隔離作用域中的屬性color。
tips:如果綁定的隔離作用域?qū)傩悦c元素的屬性名相同,則可以采取缺省寫(xiě)法。
html:<hello-world color="{{color}}"/>
js定義指令的片段:
app.directive('helloWorld',function(){
return {
scope: {
color: '@'
},
...
//配置的余下部分
}
});
方法二:使用=(=attr)進(jìn)行雙向綁定
<!doctype html>
<html ng-app="myApp">
<head>
<script src="http://cdn.staticfile.org/angular.js/1.2.10/angular.min.js"></script>
</head>
<body>
<div ng-controller='MainController'>
<input type="text" ng-model="color" placeholder="Enter a color"/>
{{color}}
<hello-world color='color'></hello-world> //注意這里的寫(xiě)法
</div>
<script>
var app = angular.module('myApp',[]);
app.controller('MainController',function(){});
app.directive('helloWorld',function(){
return {
scope:{color:'='},
restrict: 'AE',
replace: true,
template: '<div style="background-color:{{color}}">Hello World<div><input type="text" ng-model="color"></div></div>'
}
});
</script>
</body>
</html>
此處也類似上面采用了缺省的寫(xiě)法。
這里需要注意的是,我們要直接在指令運(yùn)行的那個(gè)元素上設(shè)置屬性時(shí)候,是直接將 實(shí)際的作用域模型 賦值給該屬性(這里就是color)。
這樣一個(gè)雙向綁定被建立了,改變?nèi)魏我粋€(gè)input都會(huì)改變另一個(gè)值。

方法三:使用&來(lái)調(diào)用父作用域中的函數(shù)
<!doctype html>
<html ng-app="myApp">
<head>
<script src="http://cdn.staticfile.org/angular.js/1.2.10/angular.min.js"></script>
</head>
<body>
<div ng-controller='MainController'>
<input type="text" ng-model="name" placeholder="Enter a color"/>
{{name}}
<hello-world saysomething999="say();" name="liucunjie"></hello-world> //注意這里
</div>
<script>
var app = angular.module('myApp',[]);
app.controller('MainController',function($scope){
$scope.say = function(){
alert('hello');
}
$scope.name = 'leifeng';
});
app.directive('helloWorld',function(){
return {
scope:{
saysomething:'&saysomething999',
name:'@'
},
restrict: 'AE',
replace: true,
template: '<button type="button" ng-bind="name" ng-init="saysomething();"></button>'
}
});
</script>
</body>
</html>
運(yùn)行之后,彈出alert框。
- transclude
(布爾值或者字符‘element’),默認(rèn)值為false;
這個(gè)配置選項(xiàng)可以讓我們提取包含在指令那個(gè)元素里面的內(nèi)容,再將它放置在指令模板的特定位置。當(dāng)你開(kāi)啟transclude后,你就可以使用ng-transclude來(lái)指明了應(yīng)該在什么地方放置transcluded內(nèi)容
<!doctype html>
<html ng-app="myApp">
<head>
<script src="http://cdn.staticfile.org/angular.js/1.2.10/angular.min.js"></script>
</head>
<body>
<div ng-controller='MainController'>
<div class='a'>
<p>china</p>
<hello-world>
{{name}}
</hello-world>
</div>
</div>
<script>
var app = angular.module('myApp',[]);
app.controller('MainController',function($scope){
$scope.name = 'leifeng';
});
app.directive('helloWorld',function(){
return {
scope:{},
restrict: 'AE',
transclude: true,
template: '<div class="b"><div ng-transclude>你看不見(jiàn)我</div></div>'
}
});
</script>
</body>
</html>
運(yùn)行上面的代碼,輸出
china
leifeng
另外當(dāng)開(kāi)啟transclude,會(huì)創(chuàng)建一個(gè)新的transclude空間,并且繼承了父作用域(即使Scope設(shè)置為隔離作用域),上面代碼中的{{name}}是依賴于父作用域的,仍然能被渲染出來(lái),就說(shuō)明了這點(diǎn)。
我們?cè)倏纯瓷傻膆tml為下圖所示,可以發(fā)現(xiàn)文本“你看不見(jiàn)我”消失了,這是因?yàn)楸籺ransclude內(nèi)容替換掉了。
這里的transclude內(nèi)容就是{{name}}

接下來(lái)再來(lái)看看transclude的另一個(gè)取值transclude:“element”
那
transclude:"element"與transclude:true有什么區(qū)別呢?區(qū)別在于嵌入的內(nèi)容,以上面的例子來(lái)說(shuō),
當(dāng)
transclude:true時(shí)候,嵌入的內(nèi)容為{{name}},而當(dāng)
transclude:"element"時(shí)候,嵌入的內(nèi)容為
<hello-world>
{{name}}
</hello-world>
沒(méi)錯(cuò),此時(shí)嵌入的內(nèi)容為整個(gè)元素。
將上面代碼transclude:true換成transclude:true后,再運(yùn)行,你會(huì)發(fā)現(xiàn)結(jié)果并不是和你想的一樣
再次查看生成的html代碼

你會(huì)發(fā)現(xiàn)指令綁定的元素被轉(zhuǎn)換為了一個(gè)HTML注釋
關(guān)于這方面的疑問(wèn)可以查看 transclude: 'element' is useless without replace:true 獲取更多
解決方案是加上replace: true,就正常了
這時(shí)再查看HTML代碼

注意:在一個(gè)指令的模板template上只能申明一個(gè)ng-transclude。
OK,那么現(xiàn)在問(wèn)題來(lái)了,如果我們想把嵌入部分多次放入我們的模板中要怎么辦?
則可以使用$transclude(后面再controller選項(xiàng)中會(huì)講)
或者可以使用compile函數(shù),里面有個(gè)transcludeFn參數(shù)(后面會(huì)講)
或者使用link鏈接函數(shù)。
- controller
可以是一個(gè)字符串或者函數(shù)。
若是為字符串,則將字符串當(dāng)做是控制器的名字,來(lái)查找注冊(cè)在應(yīng)用中的控制器的構(gòu)造函數(shù)
angular.module('myApp', [])
.directive('myDirective', function() {
restrict: 'A', // 始終需要
controller: 'SomeController'
})
// 應(yīng)用中其他的地方,可以是同一個(gè)文件或被index.html包含的另一個(gè)文件
angular.module('myApp')
.controller('SomeController', function($scope, $element, $attrs, $transclude) {
// 控制器邏輯放在這里
});
也可以直接在指令內(nèi)部的定義為匿名函數(shù),同樣我們可以再這里注入任何服務(wù)($log,$timeout等等)
angular.module('myApp',[])
.directive('myDirective', function() {
restrict: 'A',
controller:
function($scope, $element, $attrs, $transclude) {
// 控制器邏輯放在這里
}
});
另外還有一些特殊的服務(wù)(參數(shù))可以注入
(1)$scope,與指令元素相關(guān)聯(lián)的作用域
(2)$element,當(dāng)前指令對(duì)應(yīng)的 元素
(3)$attrs,由當(dāng)前元素的屬性組成的對(duì)象
(4)$transclude,嵌入鏈接函數(shù),實(shí)際被執(zhí)行用來(lái)克隆元素和操作DOM的函數(shù)
注意: 除非是用來(lái)定義一些可復(fù)用的行為,一般不推薦在這使用。
指令的控制器和link函數(shù)(后面會(huì)講)可以進(jìn)行互換。區(qū)別在于,控制器主要是用來(lái)提供可在指令間復(fù)用的行為但link鏈接函數(shù)只能在當(dāng)前內(nèi)部指令中定義行為,且無(wú)法再指令間復(fù)用。
html代碼:
<my-site site="###">我的博客</my-site>
js代碼:
<script>
angular.module('myApp',[]).directive('mySite', function () {
return {
restrict: 'EA',
transclude: true, //注意此處必須設(shè)置為true
controller:
function ($scope, $element,$attrs,$transclude,$log) { //在這里你可以注入你想注入的服務(wù)
$transclude(function (clone) {
var a = angular.element('<a>');
a.attr('href', $attrs.site);
a.text(clone.text());
$element.append(a);
});
$log.info("hello everyone");
}
};
});
</script>
運(yùn)行上面的代碼就是
<a href="http://m.itdecent.cn/">我的博客</a>
并且在控制臺(tái)下輸出hello everyone
讓我們看看$transclude();在這里,它可以接收兩個(gè)參數(shù),第一個(gè)是$scope,作用域,第二個(gè)是帶有參數(shù)clone的回調(diào)函數(shù)。
而這個(gè)clone實(shí)際上就是嵌入的內(nèi)容(經(jīng)過(guò)jquery包裝),可以在它上做很多DOM操作。
它還有最簡(jiǎn)單的用法就是
<script>
angular.module('myApp',[]).directive('mySite', function () {
return {
restrict: 'EA',
transclude: true,
controller:
function ($scope, $element,$attrs,$transclude,$log) {
var a = $transclude(); //$transclude()就是嵌入的內(nèi)容
$element.append(a);
}
};
});
</script>
注意:使用$transclude會(huì)生成一個(gè)新的作用域。
默認(rèn)情況下,如果我們簡(jiǎn)單實(shí)用$transclude(),那么默認(rèn)的其作用域就是$transclude生成的作用域
但是如果我們實(shí)用$transclude($scope,function(clone){}),那么作用域就是directive的作用域了
那么問(wèn)題又來(lái)了。如果我們想實(shí)用父作用域呢?
可以使用$scope.$parent
<div ng-controller='parentctrl'>
<div ng-controller='sonctrl'>
<my-site site="http://www.cnblogs.com/cunjieliu"><div>雷鋒叔叔的博客</div></my-site>
</div>
</div>
<script>
var app = angular.module('myApp',[]);
app.controller('sonctrl',function($scope){
$scope.title = 'hello son';
});
app.controller('parentctrl',function($scope){
$scope.title = 'hello parent';
});
app.directive('mySite', function () {
return {
restrict: 'EA',
transclude: true,
controller:
function ($scope, $element,$attrs,$transclude,$log) {
var a = $transclude();
$element.append(a);
$log.info($scope.title);
$log.info($scope.$parent.title);
}
};
});
</script>
同理想要一個(gè)新的作用域也可以使用$scope.$parent.new();
- controllerAs
這個(gè)選項(xiàng)的作用是可以設(shè)置你的控制器的別名
angular.module("app",[])
.controller("demoController",[function(){
this.title = "angualr";
}])
<div ng-app="app" ng-controller="demoController as demo">
{{demo.title}}
</div>
同樣的我們也可以再指令里面也這樣寫(xiě)
<script>
angular.module('myApp',[]).directive('mySite', function () {
return {
restrict: 'EA',
transclude: true,
controller:'someController',
controllerAs:'mainController'
//..其他配置
};
});
</script>
- require(字符串或者數(shù)組)
字符串代表另一個(gè)指令的名字,它將會(huì)作為link函數(shù)的第四個(gè)參數(shù)
具體用法我們可以舉個(gè)例子說(shuō)明
假設(shè)現(xiàn)在我們要編寫(xiě)兩個(gè)指令,兩個(gè)指令中的link鏈接函數(shù)中(link函數(shù)后面會(huì)講)存在有很多重合的方法,
這時(shí)候我們就可以將這些重復(fù)的方法寫(xiě)在第三個(gè)指令的controller中(上面也講到controller經(jīng)常用來(lái)提供指令間的復(fù)用行為)
然后在這兩個(gè)指令中,require這個(gè)擁有controller字段的的指令(第三個(gè)指令),
最后通過(guò)link鏈接函數(shù)的第四個(gè)參數(shù)就可以引用這些重合的方法了。
<!doctype html>
<html ng-app="myApp">
<head>
<script src="http://cdn.staticfile.org/angular.js/1.2.10/angular.min.js"></script>
</head>
<body>
<outer-directive>
<inner-directive></inner-directive>
<inner-directive2></inner-directive2>
</outer-directive>
<script>
var app = angular.module('myApp', []);
app.directive('outerDirective', function() {
return {
scope: {},
restrict: 'AE',
controller: function($scope) {
this.say = function(someDirective) {
console.log('Got:' + someDirective.message);
};
}
};
});
app.directive('innerDirective', function() {
return {
scope: {},
restrict: 'AE',
require: '^outerDirective',
link: function(scope, elem, attrs, controllerInstance) {
scope.message = "Hi,leifeng";
controllerInstance.say(scope);
}
};
});
app.directive('innerDirective2', function() {
return {
scope: {},
restrict: 'AE',
require: '^outerDirective',
link: function(scope, elem, attrs, controllerInstance) {
scope.message = "Hi,shushu";
controllerInstance.say(scope);
}
};
});
</script>
</body>
</html>
上面例子中的指令innerDirective和指令innerDirective2復(fù)用了定義在指令outerDirective的controller中的方法
也進(jìn)一步說(shuō)明了,指令中的controller是用來(lái)讓不同指令間通信用的。
另外我們可以在require的參數(shù)值加上下面的某個(gè)前綴,這會(huì)改變查找控制器的行為:
(1)沒(méi)有前綴,指令會(huì)在自身提供的控制器中進(jìn)行查找,如果找不到任何控制器,則會(huì)拋出一個(gè)error
(2)如果在當(dāng)前的指令沒(méi)有找到所需的控制器,則會(huì)將null傳給link連接函數(shù)的第四個(gè)參數(shù)
(3)如果在當(dāng)前的指令沒(méi)有找到所需的控制器,則會(huì)查找父元素的控制器
(4)組合
- Anguar的指令編譯過(guò)程
首先加載angularjs庫(kù),查找到ng-app指令,從而找到應(yīng)用的邊界,
根據(jù)ng-app劃定的作用域來(lái)調(diào)用$compile服務(wù)進(jìn)行編譯,
angularjs會(huì)遍歷整個(gè)HTML文檔,并根據(jù)js中指令的定義來(lái)處理在頁(yè)面上聲明的各個(gè)指令
按照指令的優(yōu)先級(jí)(priority)排列,根據(jù)指令中的配置參數(shù)(template,place,transclude等)轉(zhuǎn)換DOM
然后就開(kāi)始按順序執(zhí)行各指令的compile函數(shù)(如果指令上有定義compile函數(shù))對(duì)模板自身進(jìn)行轉(zhuǎn)換
注意:此處的compile函數(shù)是我們指令中配置的,跟上面說(shuō)的$compile服務(wù)不一樣。
每個(gè)compile函數(shù)執(zhí)行完后都會(huì)返回一個(gè)link函數(shù),所有的link函數(shù)會(huì)合成一個(gè)大的link函數(shù)
然后這個(gè)大的link函數(shù)就會(huì)被執(zhí)行,主要做數(shù)據(jù)綁定,通過(guò)在DOM上注冊(cè)監(jiān)聽(tīng)器來(lái)動(dòng)態(tài)修改scope中的數(shù)據(jù),
或者是使用$watchs監(jiān)聽(tīng) scope中的變量來(lái)修改DOM,從而建立雙向綁定等等。
若我們的指令中沒(méi)有配置compile函數(shù),那我們配置的link函數(shù)就會(huì)運(yùn)行,
她做的事情大致跟上面complie返回之后所有的link函數(shù)合成的的大的link函數(shù)差不多。
所以:在指令中compile與link選項(xiàng)是互斥的,如果同時(shí)設(shè)置了這兩個(gè)選項(xiàng),
那么就會(huì)把compile所返回的函數(shù)當(dāng)做是鏈接函數(shù),而link選項(xiàng)本身就會(huì)被忽略掉 - compile編譯函數(shù)和link鏈接函數(shù)
- compile編譯函數(shù)選項(xiàng)
compile選項(xiàng)可以返回一個(gè)對(duì)象或者函數(shù)
在這里我們可以在指令和實(shí)時(shí)數(shù)據(jù)被放到DOM中之前進(jìn)行DOM操作,
比如我們可以在這里進(jìn)行添加或者刪除節(jié)點(diǎn)的DOM的操作。
所以編譯函數(shù)是負(fù)責(zé)對(duì)模板的DOM進(jìn)行轉(zhuǎn)換,并且僅僅只會(huì)運(yùn)行一次。
compile函數(shù)的語(yǔ)法
compile:function compile(tElement,tAttrs,transclude){
return{
pre:function preLink(scope,iElement,iAttrs,controller){},
post:function postLink(scope,iElement,iAttrs,controller){}
}
}
對(duì)于我們編寫(xiě)的大部分的指令來(lái)說(shuō),并不需要對(duì)模板進(jìn)行轉(zhuǎn)換,所以大部分情況只要編寫(xiě)link函數(shù)就可以了。
tips:
preLink函數(shù)會(huì)在編譯階段之后,指令鏈接到子元素之前執(zhí)行
類似的,postLink會(huì)在指令鏈接到子元素之后執(zhí)行
這意味著,為了不破壞綁定過(guò)程,如果你需要修改DOM結(jié)構(gòu),你應(yīng)該在postLink函數(shù)中來(lái)做這件事。
- link鏈接函數(shù)選項(xiàng)
鏈接函數(shù)負(fù)責(zé)將作用域和DOM進(jìn)行鏈接。
可以簡(jiǎn)單理解為,當(dāng)directive被angular 編譯后,執(zhí)行該方法。
link鏈接函數(shù)舉例
angular.module('docsTransclusionExample', []).controller('Controller', ['$scope', function($scope) {
}]).directive('myDialog', function() {
return {
scope: {},
link: function (scope, element,attrs) {
//...
}
};
});
官網(wǎng)中對(duì)這三個(gè)參數(shù)的解釋:
: scope:is an Angular scope object.
: element: is the jqLite-wrapped element that this directive matches.
: attrs: is a hash object with key-value pairs of normalized attribute names and their corresponding attribute values.
我的解釋:
: link中的第一個(gè)參數(shù)scope基本上就是return中的那個(gè)scope參數(shù);
: element簡(jiǎn)單說(shuō)就是$('my-dialog'),即directive中第一個(gè)參數(shù)的名字;
: attrs是個(gè)map,內(nèi)容是你這個(gè)directive上的所有屬性。例如:你在頁(yè)面上如果這樣寫(xiě)了directive:
<my-dialog type="modal" animation="fade"></my-dialog>
那attrs就是:
{
type: 'modal',
animation: 'fade'
}
未完待續(xù)...(只是本人學(xué)習(xí)的筆記,有可能有錯(cuò)誤。。。)