angularjs directive 實例 詳解 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 張映 ?發表于? 2014-03-13 ? ??
前面提到了angularjs的factory,service,provider,這個可以理解成php的model,這種model是不帶html的,今天所說的directive,也可以理解成php的model,也可以理解成插件,只不過這種model是帶html的,例如:php的分頁函數。
一,angularjs directive的常用格式,以及參數說明
1,直接return
var ?phonecatDirectives?=?angular.module( 'phonecatDirectives' ,?[]);?? ?? phonecatDirectives.directive('directiveName' ,? function ( $inject )?{?? ?? ???return ?{?? ??? template:?'<div></div>' ,?? ?? ??? replace:?false,?? ?? ??? transclude:?true,?? ?? ??? restrict:?'E' ,?? ?? ??? scope:?{?...?},?? ?? ??????controller:?function ( $scope ,? $element ){?....?},????? ?? ??? ??compile:?function (tElement,?tAttrs,?transclude)?{?? ??? return ?{?? ??? pre:?function ?preLink(scope,?iElement,?iAttrs,?controller)?{?...?},?? ??? post:?function ?postLink(scope,?iElement,?iAttrs,?controller)?{?...?}?? ??? }?? ??? },?? ?? ??? link:?function (scope,?iElement,?iAttrs)?{?...?}?? ???};?? });?? 2,定義一個js的域
var ?phonecatDirectives?=?angular.module( 'phonecatDirectives' ,?[]);?? ?? phonecatDirectives.directive('directiveName' ,? function ( $inject )?{?? ?? ???var ?mydi?=?{?? ??? template:?'<div></div>' ,?? ??????.....................?,?? ??? link:?function (scope,?iElement,?iAttrs)?{?...?}?? ???};?? ?? ???return ?mydi;?? });?? 3,angularjs directive 對像參數說明
name - 當前scope的名稱,注冊時可以使用默認值(不填)。
priority(優先級)- 當有多個directive定義在同一個DOM元素時,有時需要明確它們的執行順序。這屬性用于在directive的compile function調用之前進行排序。如果優先級相同,則執行順序是不確定的(經初步試驗,優先級高的先執行,同級時按照類似棧的“后綁定先執行”。另外,測試時有點不小心,在定義directive的時候,兩次定義了一個相同名稱的directive,但執行結果發現,兩個compile或者link function都會執行)。
terminal(最后一組)- 如果設置為”true”,則表示當前的priority將會成為最后一組執行的directive。任何directive與當前的優先級相同的話,他們依然會執行,但順序是不確定的(雖然順序不確定,但基本上與priority的順序一致。當前優先級執行完畢后,更低優先級的將不會再執行)。
scope - 如果設置為:
true - 將為這個directive創建一個新的scope。如果在同一個元素中有多個directive需要新的scope的話,它還是只會創建一個scope。新的作用域規則不適用于根模版(root of the template),因此根模版往往會獲得一個新的scope。
{}(object hash) - 將創建一個新的、獨立(isolate)的scope。”isolate” scope與一般的scope的區別在于它不是通過原型繼承于父scope的。這對于創建可復用的組件是很有幫助的,可以有效防止讀取或者修改父級scope的數據。這個獨立的scope會創建一個擁有一組來源于父scope的本地scope屬性(local scope properties)的object hash。這些local properties對于為模版創建值的別名很有幫助(useful for aliasing values for templates -_-!)。本地的定義是對其來源的一組本地scope property的hash映射(Locals definition is a hash of local scope property to its source #&)$&@#)($&@#_):
@或@attr - 建立一個local scope property到DOM屬性的綁定。因為屬性值總是String類型,所以這個值總是返回一個字符串。如果沒有通過@attr指定屬性名稱,那么本地名稱將與DOM屬性的名稱一直。例如<widget my-attr=”hello {{name}}”>,widget的scope定義為:{localName:’@myAttr’}。那么,widget scope property的localName會映射出”hello {{name}}"轉換后的真實值。name屬性值改變后,widget scope的localName屬性也會相應地改變(僅僅單向,與下面的”=”不同)。name屬性是在父scope讀取的(不是組件scope)
=或=expression(這里也許是attr) - 在本地scope屬性與parent scope屬性之間設置雙向的綁定。如果沒有指定attr名稱,那么本地名稱將與屬性名稱一致。例如<widget my-attr=”parentModel”>,widget定義的scope為:{localModel:’=myAttr’},那么widget scope property “localName”將會映射父scope的“parentModel”。如果parentModel發生任何改變,localModel也會發生改變,反之亦然。(雙向綁定)
&或&attr - 提供一個在父scope上下文中執行一個表達式的途徑。如果沒有指定attr的名稱,那么local name將與屬性名稱一致。例如<widget my-attr=”count = count + value”>,widget的scope定義為:{localFn:’increment()’},那么isolate scope property “localFn”會指向一個包裹著increment()表達式的function。一般來說,我們希望通過一個表達式,將數據從isolate scope傳到parent scope中。這可以通過傳送一個本地變量鍵值的映射到表達式的wrapper函數中來完成。例如,如果表達式是increment(amount),那么我們可以通過localFn({amount:22})的方式調用localFn以指定amount的值(上面的例子真的沒看懂,&跑哪去了?)。
controller - controller 構造函數。controller會在pre-linking步驟之前進行初始化,并允許其他directive通過指定名稱的require進行共享(看下面的require屬性)。這將允許directive之間相互溝通,增強相互之間的行為。controller默認注入了以下本地對象:
$scope - 與當前元素結合的scope
$element - 當前的元素
$attrs - 當前元素的屬性對象
$transclude - 一個預先綁定到當前轉置scope的轉置linking function :function(cloneLinkingFn)。(A transclude linking function pre-bound to the correct transclusion scope)
require - 請求另外的controller,傳入當前directive的linking function中。require需要傳入一個directive controller的名稱。如果找不到這個名稱對應的controller,那么將會拋出一個error。名稱可以加入以下前綴:
? - 不要拋出異常。這使這個依賴變為一個可選項。
^ - 允許查找父元素的controller
restrict - EACM的子集的字符串,它限制directive為指定的聲明方式。如果省略的話,directive將僅僅允許通過屬性聲明:
E - 元素名稱: <my-directive></my-directive>
A - 屬性名: <div my-directive=”exp”></div>
C - class名: <div class=”my-directive:exp;”></div>
M - 注釋 : <!-- directive: my-directive exp -->
template - 如果replace 為true,則將模版內容替換當前的HTML元素,并將原來元素的屬性、class一并遷移;如果為false,則將模版元素當作當前元素的子元素處理。想了解更多的話,請查看“Creating Widgets”章節(在哪啊。。。Creating Components就有。。。)
templateUrl - 與template基本一致,但模版通過指定的url進行加載。因為模版加載是異步的,所以compilation、linking都會暫停,等待加載完畢后再執行。
replace - 如果設置為true,那么模版將會替換當前元素,而不是作為子元素添加到當前元素中。(注:為true時,模版必須有一個根節點)
transclude - 編譯元素的內容,使它能夠被directive所用。需要(在模版中)配合ngTransclude使用(引用)。transclusion的優點是linking function能夠得到一個預先與當前scope綁定的transclusion function。一般地,建立一個widget,創建isolate scope,transclusion不是子級的,而是isolate scope的兄弟。這將使得widget擁有私有的狀態,transclusion會被綁定到父級(pre-isolate)scope中。(上面那段話沒看懂。但實際實驗中,如果通過<any my-directive>{{name}}</any my-directive>調用myDirective,而transclude設置為true或者字符串且template中包含<sometag ng-transclude>的時候,將會將{{name}}的編譯結果插入到sometag的內容中。如果any的內容沒有被標簽包裹,那么結果sometag中將會多了一個span。如果本來有其他東西包裹的話,將維持原狀。但如果transclude設置為’element’的話,any的整體內容會出現在sometag中,且被p包裹)
true - 轉換這個directive的內容。(這個感覺上,是直接將內容編譯后搬入指定地方)
‘element’ - 轉換整個元素,包括其他優先級較低的directive。(像將整體內容編譯后,當作一個整體(外面再包裹p),插入到指定地方)
compile - 這里是compile function,將在下面實例詳細講解
link - 這里是link function ,將在下面實例詳細講解。這個屬性僅僅是在compile屬性沒有定義的情況下使用。
三,angularjs directive 實例講解
下面的實例都圍繞著,上面的參數來展開的
1,directive聲明方式實例
?? 'use?strict' ;?? ?? var ?phonecatDirectives?=?angular.module( 'phonecatDirectives' ,?[]);?? ?? phonecatDirectives.directive('myTest' ,? function ()?{?? ????return ?{?? ????????restrict:?'ACEM' ,?? ????????require :? '^ngModel' ,?? ????????scope:?{?? ????????????ngModel:?'=' ?? ????????},?? ????????template:?'<div><h4>Weather?for?{{ngModel}}</h4></div>' ?? ????}?? });?? ?? ?? 'use?strict' ;?? ?? var ?dtControllers?=?angular.module( 'dtControllers' ,?[]);?? ?? dtControllers.controller('directive1' ,[ '$scope' ,?? ????function ( $scope )?{?? ????????$scope .name?=? 'this?is?tank?test' ;?? ????}?? ]);?? ?? ?? ?? 'use?strict' ;?? ?? var ?phonecatApp?=?angular.module( 'phonecatApp' ,?[?? ????'phonecatDirectives' ,?? ????'dtControllers' ?? ]);?? ?? ?? <script?src="../lib/angular/angular.js" ></script>?? <script?src="../js/app.js" ></script>?? <script?src="../js/controller.js" ></script>?? <script?src="../js/directives.js" ></script>?? <body?ng-app="phonecatApp" >?? ????<div?ng-controller="directive1" >?? ????????<input?type="text" ?ng-model= "city" ?placeholder= "Enter?a?city" ?/>?? ?? ????????<my-test?ng-model="city" ?></my-test>?? ????????<span?my-test="exp" ?ng-model= "city" ></span>?? ????????<!--?directive:?my-test?exp ?-->?? ????????<span?ng-model="city" ></span>?? ????</div>?? </body>?? 上例結果:<!-- directive: my-test exp -->這個不起作用,不知道為什么,嘗試了好多方法都不起作用。
2,template和templateUrl區別與聯系
templateUrl其實根template功能是一樣的,只不過templateUrl加載一個html文件,上例中,我們也能發現問題,template后面根的是html的標簽,如果標簽很多呢,那就比較不爽了。可以將上例中的,template改一下。
phonecatDirectives.directive( 'myTest' ,? function ()?{?? ????return ?{?? ????????restrict:?'ACEM' ,?? ????????require :? '^ngModel' ,?? ????????scope:?{?? ????????????ngModel:?'=' ?? ????????},?? ????????templateUrl:'../partials/tem1.html' ??? ?? ????}?? });?? 3,scope重定義
?? phonecatDirectives.directive('myAttr' ,? function ()?{?? ????return ?{?? ????????restrict:?'E' ,?? ????????scope:?{?? ????????????customerInfo:?'=info' ?? ????????},?? ????????template:?'Name:?{{customerInfo.name}}?Address:?{{customerInfo.address}}<br>' ?+?? ??????????????????'Name:?{{vojta.name}}?Address:?{{vojta.address}}' ?? ????};?? });?? ?? ?? dtControllers.controller('attrtest' ,[ '$scope' ,?? ????function ( $scope )?{?? ????????$scope .naomi?=?{?name:? 'Naomi' ,?address:? '1600?Amphitheatre' ?};?? ????????$scope .vojta?=?{?name:? 'Vojta' ,?address:? '3456?Somewhere?Else' ?};?? ????}?? ]);?? ?? ?? <body?ng-app="phonecatApp" >?? ????<div?ng-controller="attrtest" >?? ????????<my-attr?info="naomi" ></my-attr>?? ????</div>?? </body>?? 運行結果:
Name:?Naomi?Address:?1600?Amphitheatre?????? ?? Name:?Address:????????? 可能把上面的directive簡單改一下,
phonecatDirectives.directive( 'myAttr' ,? function ()?{?? ????return ?{?? ????????restrict:?'E' ,?? ????????template:?'Name:?{{customerInfo.name}}?Address:?{{customerInfo.address}}<br>' ?+?? ??????????????????'Name:?{{vojta.name}}?Address:?{{vojta.address}}' ?? ????};?? });?? 運行結果如下:根上面正好相反
Name:?Address:?? Name:?Vojta?Address:?3456?Somewhere?Else?? 4,transclude的使用
transclude的用法,有點像jquery里面的$().html()功能
?? phonecatDirectives.directive('myEvent' ,? function ()?{?? ????return ?{?? ????????restrict:?'E' ,?? ????????transclude:?true,?? ????????scope:?{?? ????????????'close' :? '&onClick' ????? ?? ????????},?? ????????templateUrl:?'../partials/event_part.html' ?? ????};?? });?? ?? ?? dtControllers.controller('eventtest' ,[ '$scope' , '$timeout' ,?? ????function ( $scope ,? $timeout )?{?? ????????$scope .name?=? 'Tobias' ;?? ????????$scope .hideDialog?=? function ?()?{?? ????????????$scope .dialogIsHidden?=?true;?? ????????????$timeout ( function ?()?{?? ????????????????$scope .dialogIsHidden?=?false;?? ????????????},?2000);?? ????????};?? ????}?? ]);?? ?? ?? <body?ng-app="phonecatApp" >?? ????<div?ng-controller="eventtest" >?? ????????<my-event?ng-hide="dialogIsHidden" ?on-click= "hideDialog()" >?? ????????????Check?out?the?contents,?{{name}}!?? ????????</my-event>?? ????</div>?? </body>?? ?? ?? <div>?? ????<a?href?ng-click="close()" >×</a>?? ????<div?ng-transclude></div>?? </div>?? 5,controller,link,compile有什么不同
?? phonecatDirectives.directive('exampleDirective' ,? function ()?{?? ????return ?{?? ????????restrict:?'E' ,?? ????????template:?'<p>Hello?{{number}}!</p>' ,?? ????????controller:?function ( $scope ,? $element ){?? ????????????$scope .number?=? $scope .number?+? "22222?" ;?? ????????},?? ????????link:?function (scope,?el,?attr)?{?? ????????????scope.number?=?scope.number?+?"33333?" ;?? ????????},?? ????????compile:?function (element,?attributes)?{?? ????????????return ?{?? ????????????????pre:?function ?preLink(scope,?element,?attributes)?{?? ????????????????????scope.number?=?scope.number?+?"44444?" ;?? ????????????????},?? ????????????????post:?function ?postLink(scope,?element,?attributes)?{?? ????????????????????scope.number?=?scope.number?+?"55555?" ;?? ????????????????}?? ????????????};?? ????????}?? ????}?? });?? ?? ?? dtControllers.controller('directive2' ,[ '$scope' ,?? ????function ( $scope )?{?? ????????$scope .number?=? '1111?' ;?? ????}?? ]);?? ?? ?? <body?ng-app="phonecatApp" >?? ????<div?ng-controller="directive2" >?? ????????<example-directive></example-directive>?? ????</div>?? </body>?? 運行結果:
Hello?1111?22222?44444?55555?!?? 由結果可以看出來,controller先運行,compile后運行,link不運行。
將上例中的compile注釋掉
?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 運行結果:
Hello?1111?22222?33333?!?? 由結果可以看出來,controller先運行,link后運行,link和compile不兼容。
作者:海底蒼鷹 地址:http://blog.51yip.com/jsjquery/1607.html
=============================
在angular中我們定義directive方法時,可以看到
?
[html] ?view plaincopy
return?{?? ????restrict:?'AE',?? ????scope:?{},?? ????template:?'< div > </ div > ',?? ????link:?function()?{}?? }??
除了代碼中出現的屬性,還有一些其他的屬性可供配置,這里不作詳述。
今天我們要說的重點是scope 字段。
常規用法設置
[javascript] ?view plaincopy
scope:?{?? ????name:?'=' ,?? ????age:?'=' ,?? ????sex:?'@' ,?? ????say:?'&' ?? }?? 假設我們的hml代碼如下
[html] ?view plaincopy
< div ?my-directive? name = "myName" ? age = "myAge" ? sex = "male" ? say = "say()" > </ div > ?? 對應的controller部分代碼
[javascript] ?view plaincopy
function ?Controller($scope)?{?? ????$scope.name?=?'Pajjket' ;?? ????$scope.age?=?99;?? ????$scope.sex?=?'我是男的' ;?? ????$scope.say?=?function ()?{?? ????????alert('Hello,我是彈出消息' );?? ????};?? }?? 那這幾種修飾符的含義又是什么呢,他們如何關聯起來的
”=“:指令中的屬性取值為controller中對應$scope上屬性的取值,可用于雙向數據的綁定
”@“:指令中的取值為html中的字面量/直接量;建立一個local scope property到DOM屬性的綁定。因為屬性值總是String類型,所以這個值總是返回一個字符串。如果沒有通過@attr指定屬性名稱,那么本地名稱將與DOM屬性的名稱一直。例如<widget my-attr=”hello {{name}}”>,widget的scope定義為:{localName:’@myAttr’}。那么,widget scope property的localName會映射出”hello {{name}}"轉換后的真實值。name屬性值改變后,widget scope的localName屬性也會相應地改變(僅僅單向,與下面的”=”不同)。name屬性是在父scope讀取的(不是組件scope)
”&“:指令中的取值為Contoller中對應$scope上的屬性,但是這屬性必須為一個函數回調
總結
以上是生活随笔 為你收集整理的angularjs directive 实例 详解 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。