您好,登錄后才能下訂單哦!
這篇文章主要介紹了Angular中Directive怎么用,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
Directive可能是AngularJS中比較復雜的一個東西了。一般我們將其理解成指令。AngularJS自帶了不少預設的指令,比如ng-app,ng-controller這些。可以發現個特點,AngularJS自帶的指令都是由ng-打頭的。
那么,Directive究竟是個怎么樣的一個東西呢?我個人的理解是這樣的:將一段html、js封裝在一起,形成一個可復用的獨立個體,具體特定的功能。下面我們來詳細解讀一下Directive的一般性用法。
var myDirective = angular.module('directives', []); myDirective.directive('directiveName', function($inject) { return { template: '<div></div>', replace: false, transclude: true, restrict: 'E', scope: {}, controller: function($scope, $element) { }, complie: function(tElement, tAttrs, transclude) { return { pre: function preLink(scope, iElement, iAttrs, controller) { }, post: function postLink(scope, iElement, iAttrs, controller) { } }; }, link: function(scope, iElement, iAttrs) { } }; });
這里直接return了一個object,對象中包括比較多的屬性,這些屬性都是對自定義directive的定義。詳細的含義,下面會繼續說明。
return對象參數說明
return { name: '', priority: 0, terminal: true, scope: {}, controller: fn, require: fn, restrict: '', template: '', templateUrl: '', replace: '', transclude: true, compile: fn, link: fn }
相關教程推薦:《angular教程》
如上所示,return的對象中會有很多的屬性,這行屬性都是用來定義directive的。
name
表示當前scope的名稱,一般聲明時使用默認值,不用手動設置此屬性。
priority
優先級。當有多個directive定義在同一個DOM元素上時,有時需要明確他們的執行順序。這個屬性用于在directive的compile function調用之前進行排序。如果優先級相同,則執行順序是不確定的(根據經驗,優先級高的先執行,相同優先級時按照先綁定后執行)。
teminal
最后一組。如果設置為true,則表示當前的priority將會成為最后一組執行的directive,即比此directive的priority更低的directive將不會執行。同優先級依然會執行,但是順序不確定。
scope
將創建一個新的、獨立的scope,此scope與一般的scope的區別在于它不是通過原型繼承于父scope的。這對于創建可復用的組件是很有幫助的,可以有效的防止讀取或者修改父級scope的數據。這個獨立的scope會創建一個擁有一組來源于父scope的本地scope屬性hash集合。這些本地scope屬性對于模版創建值的別名很有幫助。本地的定義是對其來源的一組本地scope property的hash映射。
將為這個directive創建一個新的scope。如果在同一個元素中有多個directive需要新的scope的話,它還是只會創建一個scope。新的作用域規則不適用于根模版,因為根模版往往會獲得一個新的scope。
true
{}
controller
$scope 與當前元素結合的scope
$element 當前的元素
$attrs 當前元素的屬性對象
$transclude 一個預先綁定到當前scope的轉置linking function
controller構造函數。controller會在pre-linking步驟之前進行初始化,并允許其他directive通過指定名稱的require進行共享。這將允許directive之間相互溝通,增強相互之間的行為。controller默認注入了以下本地對象:
require
? 不要拋出異常。這將使得這個依賴變為一個可選項
^ 允許查找父元素的controller
請求另外的controller,傳入當前directive的linking function中。require需要傳入一個directive controller的名稱。如果找不到這個名稱對應的controller,那么將會拋出一個error。名稱可以加入以下前綴:
restrict
E 元素名稱:
A 屬性名:
C class名:
M 注釋:
EACM的子集的字符串,它限制了directive為指定的聲明方式。如果省略的話,directive將僅僅允許通過屬性聲明
template
如果replace為true,則將模版內容替換當前的html元素,并將原來元素的屬性、class一并轉移;如果replace為false,則將模版元素當作當前元素的子元素處理。
templateUrl
與template基本一致,但模版通過指定的url進行加載。因為模版加載是異步的,所有compilation、linking都會暫停,等待加載完畢后再執行。
replace
如果設置為true,那么模版將會替換當前元素,而不是作為子元素添加到當前元素中。(為true時,模版必須有一個根節點)
transclude
true/false
轉換這個directive的內容。(這個感覺上,是直接將內容編譯后搬入指定地方)
‘element’
轉換整個元素,包括其他優先級較低的directive。(像將整體內容編譯后,當作一個整體(外面再包裹p),插入到指定地方)
編譯元素的內容,使它能夠被directive使用。需要在模版中配合ngTransclude使用。transclusion的有點是linking function能夠得到一個預先與當前scope綁定的transclusion function。一般地,建立一個widget,創建獨立scope,transclusion不是子級的,而是獨立scope的兄弟級。這將使得widget擁有私有的狀態,transclusion會被綁定到父級scope中。(上面那段話沒看懂。但實際實驗中,如果通過調用myDirective,而transclude設置為true或者字符串且template中包含的時候,將會將的編譯結果插入到sometag的內容中。如果any的內容沒有被標簽包裹,那么結果sometag中將會多了一個span。如果本來有其他東西包裹的話,將維持原狀。但如果transclude設置為’element’的話,any的整體內容會出現在sometag中,且被p包裹)
compile
這里是compile function,將在下面實例詳細說明
link
這里是link function ,將在下面實例詳細講解。這個屬性僅僅是在compile屬性沒有定義的情況下使用。
這里關于directive的scope為一個object時,有更多的內容非常有必要說明一下。看下面的代碼:
scope: { name: '=', age: '=', sex: '@', say: '&' }
這個scope中關于各種屬性的配置出現了一些奇怪的前綴符號,有=,@,&,那么這些符號具體的含義是什么呢?再看下面的代碼:
html
<div my-directive name="myName" age="myAge" sex="male" say="say()"></div>復制代碼
javascript
function Controller($scope) { $scope.name = 'Pajjket'; $scope.age = 99; $scope.sex = '我是男的'; $scope.say = function() { alert('Hello,我是彈出消息'); }; }
=
: 指令中的屬性取值為Controller中對應$scope上屬性的取值
@
: 指令中的取值為html中的字面量/直接量
&
: 指令中的取值為Controller中對應$scope上的屬性,但是這個屬性必須為一個函數回調
下面是更加官方的解釋:
=
或者=expression/attr
例如: 中,widget定義的scope為:{localModel: '=myAttr'},那么widget scope property中的localName將會映射父scope的parentModel。如果parentModel發生任何改變,localModel也會發生改變,反之亦然。即雙向綁定。
@或者@attr 建立一個local scope property到DOM屬性的綁定。因為屬性值總是String類型,所以這個值總返回一個字符串。如果沒有通過@attr指定屬性名稱,那么本地名稱將與DOM屬性的名稱一致。 例如: ,widget的scope定義為:{localName: '@myAttr'}。那么,widget scope property的localName會映射出"hello "轉換后的真實值。當name屬性值發生改變后,widget scope的localName屬性也會相應的改變(僅僅是單向,與上面的=不同)。那么屬性是在父scope讀取的(不是從組件的scope讀取的)
&或者&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的值。
下面的示例都圍繞著上面所作的參數說明而展開的。
directive聲明實例
// 自定義directive var myDirective = angular.modeule('directives', []); myDirective.directive('myTest', function() { return { restrict: 'EMAC', require: '^ngModel', scope: { ngModel: '=' }, template: '<div><h5>Weather for {{ngModel}}</h5</div>' }; }); // 定義controller var myControllers = angular.module('controllers', []); myControllers.controller('testController', [ '$scope', function($scope) { $scope.name = 'this is directive1'; } ]); var app = angular.module('testApp', [ 'directives', 'controllers' ]); <body ng-app="testApp"> <div ng-controller="testController"> <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> <span ng-model="city"></span> </div> </body>
templateUrl其實根template功能是一樣的,只不過templateUrl加載一個html文件,上例中,我們也能發現問題,template后面根的是html的標簽,如果標簽很多呢,那就比較不爽了。可以將上例中的,template改一下。
myDirective.directive('myTest', function() { return { restrict: 'EMAC', require: '^ngModel', scope: { ngModel: '=' }, templateUrl:'../partials/tem1.html' //tem1.html中的內容就是上例中template的內容。 } });
//directives.js中定義myAttr myDirectives.directive('myAttr', function() { return { restrict: 'E', scope: { customerInfo: '=info' }, template: 'Name: {{customerInfo.name}} Address: {{customerInfo.address}}<br>' + 'Name: {{vojta.name}} Address: {{vojta.address}}' }; }); //controller.js中定義attrtest myControllers.controller('attrtest',['$scope', function($scope) { $scope.naomi = { name: 'Naomi', address: '1600 Amphitheatre' }; $scope.vojta = { name: 'Vojta', address: '3456 Somewhere Else' }; } ]); // html中 <body ng-app="testApp"> <div ng-controller="attrtest"> <my-attr info="naomi"></my-attr> </div> </body>
Name: Naomi Address: 1600 Amphitheatre //有值,因為customerInfo定義過的 Name: Address: //沒值 ,因為scope重定義后,vojta是沒有定義的
myDirectives.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
因為此時的directive沒有定義獨立的scope,customerInfo是undefined,所以結果正好與上面相反。
transclude的用法,有點像jquery里面的$().html()功能
myDirective.directive('myEvent', function() { return { restrict: 'E', transclude: true, scope: { 'close': '$onClick' //根html中的on-click="hideDialog()"有關聯關系 }, templateUrl: '../partials/event_part.html' }; }); myController.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> <!--event_part.html --> <div> <a href ng-click="close()">×</a> <div ng-transclude></div> </div>
說明:這段html最終的結構應該如下所示:
<body ng-app="phonecatApp"> <div ng-controller="eventtest"> <div ng-hide="dialogIsHidden" on-click="hideDialog()"> <span>Check out the contents, {{name}}!</span> </div> </div> </body>
將原來的html元素中的元素Check out the contents, !插入到模版的中,還會另外附加一個標簽。controller
,link
,compile
之間的關系
myDirective.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 "; } }; } } }); //controller.js添加 myController.controller('directive2',[ '$scope', function($scope) { $scope.number = '1111 '; } ]); //html <body ng-app="testApp"> <div ng-controller="directive2"> <example-directive></example-directive> </div> </body>
上面小例子的運行結果如下:
Hello 1111 22222 44444 5555 !
由結果可以看出來,controller先運行,compile后運行,link不運行。 我們現在將compile屬性注釋掉后,得到的運行結果如下:
Hello 1111 22222 33333
!
感謝你能夠認真閱讀完這篇文章,希望小編分享的“Angular中Directive怎么用”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。