var app = angular.module("app",[]);
//第一個(gè)參數(shù):指令的名稱,使用駝峰命名
//第二個(gè)參數(shù):回調(diào)函數(shù),回調(diào)函數(shù)內(nèi)部返回對(duì)象
app.directive("hiHello",function () {
return {
//執(zhí)行的代碼,參數(shù),寫在這里
}
});
directive的參數(shù)
restrict : String
設(shè)置自定義指令的html格式
restrict的取值表
| E | C | M | A |
|---|---|---|---|
| element | attribute | class | 注釋 |
<body>
<!-- 1 : 使用指令的第一種方式 -->
<hi-hello>若其中有內(nèi)容,則被替換掉</hi-hello>
<!-- 2: 屬性 -->
<div hi-hello></div>
<!-- 3:類名 -->
<div class="hi-hello"></div>
<!-- 4:注釋 指令名后面保留一個(gè)空格 -->
<!-- directive:hi-hello -->
</body>
<script type="text/javascript">
var app = angular.module("app",[]);
app.directive("hiHello",function () {
return {
/* ECMA
* E : element
* A : attribute
* C : class
* M : 注釋
*/
restrict:"EACM",//可以組合使用,順序不限,得大寫 (默認(rèn)值為EA)
// 如果使用M,必須得配合使用 replace(替換)
replace:true,//默認(rèn)值為false 表示是否替換當(dāng)前元素
//設(shè)置模板
template:"<h1>隨便寫的信息</h1>",
}
});
</script>
replace : Boolean or String
(布爾型)默認(rèn)為false(模板內(nèi)容會(huì)加載到標(biāo)簽內(nèi)部),true(模板內(nèi)容會(huì)替換當(dāng)前標(biāo)簽),即是否替換當(dāng)前元素中已有的內(nèi)容
replace:true,
注意:如果使用M,必須得配合使用 replace(替換)
priority : Number
優(yōu)先級(jí),可忽略,默認(rèn)為0
注意: ng-repeat 的優(yōu)先級(jí)為1000,這樣就可以保證在同一元素上,它總是在其他指令之前被調(diào)用
terminal : Boolean
如果為false,則Angular停止運(yùn)行當(dāng)前元素上比本指令優(yōu)先級(jí)低的指令。優(yōu)先級(jí)相同的指令還是會(huì)被執(zhí)行
注意: ng-if 的優(yōu)先級(jí)略高于 ng-view
priority和terminal的綜合運(yùn)用
<body>
<hello well good>
<div>Hello World!!!</div>
</hello>
</body>
<script src="js/angular.min.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
//terminal和priority兩個(gè)參數(shù)只能在同一個(gè)元素上設(shè)置多個(gè)指令才有效
app.directive("hello",function(){
return {
restrict : "E",
priority : 1,
link : function(){
console.log("hello");
}
}
});
app.directive("well",function(){
return {
restrict : "A",
priority : 2,
link : function(){
console.log("well");
}
}
});
app.directive("good",function(){
return {
restrict : "A",
terminal : true, //這里為true,hello、well指令將停止執(zhí)行
priority : 3,
link : function(){
console.log("good");
}
}
});
app.controller("myCtrl",function($scope){
})
</script>
template : String or Template Function
設(shè)置模板,必須設(shè)置
template:"<h1>隨便寫的信息</h1>",
//template:function(tElement, tAttrs){...},
templateUrl: String
(字符串或函數(shù))
- 外部路徑的字符串
- 接受兩個(gè)參數(shù)的函數(shù),參數(shù)為 tElement 和 tAttrs ,并返回一個(gè)外部HTML文件路徑的字符串
- 模板加載后,AngularJS會(huì)將它默認(rèn)緩存到$templateCach服務(wù)中。
注意:templateUrl 可以提前加載模塊到緩存中,提高加載速度
templateUrl : "html/first.html",
scope: Boolean or Object
當(dāng)一個(gè)控制器實(shí)現(xiàn)多個(gè)數(shù)據(jù)時(shí),就需要用到scope屬性實(shí)現(xiàn)不同的數(shù)據(jù)。如果要?jiǎng)?chuàng)建一個(gè)能夠從外部原型繼承作用域的指令,將 scope 屬性設(shè)置為 true
scope屬性的獨(dú)立作用域
- 為true時(shí),從父作用域繼承并創(chuàng)建一個(gè)自己的作用域
- 為false(默認(rèn))時(shí),全部繼承父作用域
1).controller屬性
配置屬于每個(gè)指令自己作用域上的數(shù)據(jù)(共有),而ng-controller 的作用就是從父級(jí)作用域繼承并創(chuàng)建一個(gè)新的子作用域。
controller : function($scope){
$scope.age = 20
}
設(shè)置為一個(gè)對(duì)象,則能設(shè)置 隔離作用域, scope 屬性設(shè)置為一個(gè)空對(duì)象 {} 。如果這樣做了,指令的模板就無(wú)法訪問(wèn)外部作用域了,代碼如下:
directive('myDirective', function() {
return {
restrict: 'A',
scope: {},
priority: 100,
template: '<div>Inside myDirective {{ myProperty }}</div>'
};
});
隔離作用域
將scope屬性設(shè)置為一個(gè)對(duì)象,而不是布爾值。隔離作用域默認(rèn)和父作用域沒(méi)關(guān)系,無(wú)法繼承它的屬性
1). 設(shè)置模板中數(shù)據(jù)的作用域和綁定規(guī)則:
| @ | = | & |
|---|---|---|
| 把當(dāng)前屬性作為字符串傳遞 | 與父作用域中的屬性進(jìn)行綁定 | 與父作用域中的函數(shù)進(jìn)行綁定 |
- "@" : 本地作用域?qū)傩裕菏褂卯?dāng)前指令中的數(shù)據(jù)和DOM屬性的值進(jìn)行綁定
- “=” : 雙向綁定:本地作用域上的屬性同父級(jí)作用域上的屬性進(jìn)行雙向的數(shù)據(jù)綁定。
- “&” : 父級(jí)作用域綁定:通過(guò) & 符號(hào)可以對(duì)父級(jí)作用域進(jìn)行綁定
scope : {
name : "@" //屬性和標(biāo)簽內(nèi)的屬性寫一樣
}
scope: {
ngModel: '=', // 將ngModel同指定對(duì)象綁定
onSend: '&', // 將引用傳遞給這個(gè)方法
fromName: '@' // 儲(chǔ)存與fromName相關(guān)聯(lián)的字符串
}
transclude: Boolean
默認(rèn)為false,需要?jiǎng)?chuàng)建一個(gè)可以包含任意內(nèi)容的指令時(shí), 才使用 transclude: true 。
注意:只要使用了 transclude 參數(shù),那么在控制器(下面馬上會(huì)介紹)中就無(wú)法正常監(jiān)聽數(shù)據(jù)模型的變化了
controller: String or function
controller: String or function(scope, element, attrs, transclude, otherInjectables) { ... }
注冊(cè)在應(yīng)用中的控制器的構(gòu)造函數(shù),使用函數(shù)創(chuàng)建內(nèi)聯(lián)控制器
angular.module('myApp',[]).directive('myDirective', function() {
restrict: 'A',
controller:function($scope, $element, $attrs, $transclude) {
// 控制器邏輯放在這里
}
})
controllerAs: String
可以在指令中創(chuàng)建匿名控制器
angular.module('myApp',[]).directive('myDirective', function() {
return {
restrict: 'A',
template: '<h4>{{ myController.msg }}</h4>',
controllerAs: 'myController',
controller: function() {
this.msg = "Hello World"
}
};
});
require: String
(字符串或數(shù)組)字符串代表另外一個(gè)指令的名字,如果沒(méi)有前綴,指令將會(huì)在自身所提供的控制器中進(jìn)行查找,如果沒(méi)有找到任何控制器(或具有指定名字的指令)就拋出一個(gè)錯(cuò)誤。例如:
- 如果不使用 ^ 前綴,指令只會(huì)在自身的元素上查找控制器。
require: 'ngModel' - 使用 **? ** 如果在當(dāng)前指令中沒(méi)有找到所需要的控制器,會(huì)將 null 作為傳給 link 函數(shù)的第四個(gè)參數(shù)
require: '?ngModel' - 使用 ** ^ ** 如果添加了 ^ 前綴,指令會(huì)在上游的指令鏈中查找 require 參數(shù)所指定的控制器。
require: '^ngModel' - 使用 **^? **將前面兩個(gè)選項(xiàng)的行為組合起來(lái),我們可選擇地加載需要的指令并在父指令鏈中進(jìn)行查找。
require: '^?ngModel',
link和compile
link: link: function(scope, iElement, iAttrs) { ... },
compile: compile: function(tElement, tAttrs, transclude) { ... },
- compile 選項(xiàng)本身并不會(huì)被頻繁使用,但是 link 函數(shù)則會(huì)被經(jīng)常使用。當(dāng)我們?cè)O(shè)置了 link 選項(xiàng), 實(shí)際上是創(chuàng)建了一個(gè) postLink() 鏈接函數(shù), 以便 compile() 函數(shù)可以定義鏈接函數(shù)。
- compile 和 link 選項(xiàng)是互斥的。如果同時(shí)設(shè)置了這兩個(gè)選項(xiàng),那么會(huì)把 - compile所返回的函數(shù)當(dāng)作鏈接函數(shù),而 link 選項(xiàng)本身則會(huì)被忽略。
- 通常情況下,如果設(shè)置了 compile 函數(shù),說(shuō)明我們希望在指令和實(shí)時(shí)數(shù)據(jù)被放到DOM中之前進(jìn)行DOM操作,在這個(gè)函數(shù)中進(jìn)行諸如添加和刪除節(jié)點(diǎn)等DOM操作是安全的。
//用 link 函數(shù)創(chuàng)建可以操作DOM的指令。
require : 'SomeController',
link: function(scope, element, attrs, SomeController) {
// 在這里操作DOM,可以訪問(wèn)required指定的控制器
}
compile: function(tElement, tAttrs, transclude) {
return {
pre: function(scope, iElement, iAttrs, controller) { ... },
post: function(scope, iElement, iAttrs, controller) { ... }
}
// 或者
return function postLink(...) { ... }
}
};
注意:指令的生命周期開始于 $compile 方法并結(jié)束于 link 方法