除了 AngularJS 內(nèi)置的指令外,我們還可以創(chuàng)建自定義指令。
你可以使用.directive函數(shù)來添加自定義的指令。
要調(diào)用自定義指令,HTML 元素上需要添加自定義指令名。
使用駝峰法來命名一個指令,runoobDirective, 但在使用它時需要以-分割,runoob-directive:
eg:
<body ng-app = "myapp">
? ? <my-directive></my-directive>
? ? <script>
? ? ? ? let app = angular.module("myapp",[]);
? ? ? ? app.directive("myDirective",function(){
? ? ? ? ? ? ? return {
? ? ? ? ? ? ? ? ? ? ? ? template:"<h3>自定義指令</h3>"
? ? ? ? ? ? ? }
? ? ? ? });
? ? </script>
當(dāng)然,除了通過元素名的方式來調(diào)用指令,還可以通過以下方式來調(diào)用:
eg:
1.元素名:<my-directive></my-directive>
2.屬性:<div my-directive></div>
3.類名:<div class="my-directive"></div>
4.注釋:<!-- directive: my-directive -->
你也可以限制你的指令只能通過特定的方式來調(diào)用,通過添加restrict屬性,并設(shè)置只值為“A”,來設(shè)置指令只能通過屬性的方式來調(diào)用:
eg:
let app = angular.module("myApp", []);
app.directive("myDirective",function() {
? ? ? ? return{
? ? ? ? ? ? ? ? restrict :"A",
? ? ? ? ? ? ? ?template :"自定義指令"
? ? ? ? ?};
});
1.restrict值可以是以下幾種:
? ? ? ? ?E:作為元素名使用
? ? ? ? ?C:作為類名使用
? ? ? ? ?M:作為注釋使用
? ? ? ? ?A:作為屬性使用
2.template和templateUrl
同一個指令中只能template和templateUrl只能選其一。
template為模板內(nèi)容。即你要在指令所在的容器中插入的html代碼。
template屬性接收一個字符串,類似這樣:
template: '我是指令生成的內(nèi)容';
templateUrl為從指定地址獲取模板內(nèi)容。即你要在指令所在的容器中插入的一個.html文件。
有了templateUrl我們就可以將想實(shí)現(xiàn)的內(nèi)容寫成一個單獨(dú)的html模版,在需要的地方插入,使用起來會很舒服。
這里的templateUrl類似于JSP中的include,angular也有一個ng-include指令。
3.replace和transclude
replace:是否用模板替換當(dāng)前元素。true:將指令標(biāo)簽替換成temple中定義的內(nèi)容,頁面上不會再有標(biāo)簽;false:則append(追加)在當(dāng)前元素上,即模板的內(nèi)容包在標(biāo)簽內(nèi)部。默認(rèn)false。
transculde:是否使用ng-transculde來包含html中指令包含的所有內(nèi)容,接受兩個參數(shù)true/false。
eg: replace
js:
let app = angular.module("app",[]);
app.directive("hello",function() {
? ? ? let option ={
? ? ? ? ? ?restrict:"AECM",
? ? ? ? ? ?template:"hello , directive",
? ? ? ? ? ?replace:true? //這里replace為true,所以原來的內(nèi)容會被template代替
? ? ? ?};
? ? ? ?return option;
});
html:
<body>
? ? <hello>我是原來的內(nèi)容</hello>
? ? ===>變成<h3>hello, directive</h3>
? ? 如果replace為false ===>
? ? <hello><h3>hello,directive</h3></hello>
</body>
eg: transclude
js:
let app = angular.module("app", []);
app.directive("hello",function() {
? ? ? ?let option ={
? ? ? ? ? ? ? restrict:"AECM",
? ? ? ? ? ? ? template:"hello,directive",
? ? ? ? ? ? ? transculde:true//這里transculde為true,所以原來的內(nèi)容會被放在有ng-transclude屬性的標(biāo)簽內(nèi)
? ? ? ? ?};
? ? ? ? ?return ?option;
});
html:
<body>
? ? ? ? ?<hello>我是原來的內(nèi)容</hello>===>
? ? ? ? ?變成<hello><h3>hello,directive</h3><span ng-transclude>我是原來的內(nèi)容</span></hello>
</body>
4.指令中的scope
directive默認(rèn)能共享父 scope中定義的屬性,例如在模版中直接使用父 scope 中的對象和屬性。通常使用這種直接共享的方式可以實(shí)現(xiàn)一些簡單的 directive 功能。
但是,當(dāng)你要創(chuàng)建一個可以重復(fù)使用的directive的時候,就不能依賴于父scope了,因?yàn)樵诓煌牡胤绞褂胐irective對應(yīng)的父scope不一樣。
所以你需要一個隔離的scope,我們可以向下面這樣來定義我們的scope。
eg:
module1.directive("testDirective", function () {
? ? ? ? return {
? ? ? ? ? ? ? ? ?scope: {
? ? ? ? ? ? ? ? ? ? ? ? ? ?value: '提莫隊(duì)長正在待命!'
? ? ? ? ? ? ? ? ? },
? ? ? ? ? ? ? ? ? template: 'Say:{{value}}'
? ? ? ? }
});
這樣就很方便的將我們directive的上下文scope給定義出來了,但是,如果我想將父scope中的屬性傳遞給directive的scope怎么辦呢?
directive 在使用隔離 scope 的時候,提供了三種方法同隔離之外的地方交互:
1.@ 綁定一個局部 scope 屬性到當(dāng)前 dom 節(jié)點(diǎn)的屬性值。結(jié)果總是一個字符串,因?yàn)?dom 屬性是字符串。
2.& 提供一種方式執(zhí)行一個表達(dá)式在父 scope 的上下文中。如果沒有指定 attr 名稱,則屬性名稱為相同的本地名稱。
3.= 通過 directive 的 attr 屬性的值在局部 scope 的屬性和父 scope 屬性名之間建立雙向綁定。
以上三種方式都要在directive的attr屬性中進(jìn)行賦值。上面的話理解起來可能會比較困難,簡單來說就是:
1.@:只能綁定字符串,所以一些簡單的繼承父scope的屬性使用@
2.=: 需要實(shí)現(xiàn)雙向數(shù)據(jù)綁定的時候使用=
3.&: 傳遞來自父$scope中的函數(shù)稍后調(diào)用