http://www.cooklife.cn/detail/54bfbbd2fc2d96d1341b
w3c制定的html標準中,html的標籤以及標籤的屬性值有限,不能滿足一些特定化的需求,在angular中可以通過指令是對html中的標籤以及標籤屬性做的一個擴展。
首先我們來看看一個內置的指令,瞭解瞭解指令到底是一個神馬東東?
我們先拿指令ng-src開刀
<img src="{{path}}"/> <img ng-src="{{path}}"/>
上面兩個img標籤看出來什麼區別沒有?好吧如果沒有看出來那麼我們放到瀏覽器裏面跑一下就知道了
咦,一個圖片出來了一個加載失敗,仔細看一下一個標籤內的屬性是src,另外一個是ng-src,f12看看網頁的源碼
第二個img標籤內並沒有src屬性,但是通過瀏覽器查看網頁源代碼,第二個標籤內多了一個src屬性,切屬性值同ng-src一致,什麼情況?
原來angular的加載是在網頁渲染完畢之後纔開始的,當瀏覽器加載到img標籤時,angular的數據綁定並未生效,{{path}}並未被解析,當然加載不到圖片。那麼ng-src是如何工作的呢?欲知詳情,請移步源代碼進行查看吧!
下面通過一個簡單的指令來了解如何創建自定義指令以及如何使用指令?
angular.module('myApp', []) .directive('myDirective', function() { return { restrict: 'E', template: '<a href="http://google.com">Click me to go to Google</a>' }; });
上面的指令執行時什麼效果
<my-directive></my-directive>
我們來看看指令中restrict,template這些屬性是幹嘛用的吧?
通過module.directive('directivename', function(){})我們可以定義指令,該方法接受兩個參數
1.name
爲指令的名字,用來愛視圖中引用特定的指令
2.factory_function
該函數返回對象,其中定義了指令的全部行爲,$complile服務利用這個方法返回的對象來構造指令的行爲
var myModule = angular.module(...); * * myModule.directive('directiveName', function factory(injectables) { * var directiveDefinitionObject = { * priority: 0, * template: '<div></div>', // or // function(tElement, tAttrs) { ... }, * // or * // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... }, * transclude: false, * restrict: 'A', * templateNamespace: 'html', * scope: false, * controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... }, * controllerAs: 'stringAlias', * require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'], * compile: function compile(tElement, tAttrs, transclude) { * return { * pre: function preLink(scope, iElement, iAttrs, controller) { ... }, * post: function postLink(scope, iElement, iAttrs, controller) { ... } * } * // or * // return function postLink( ... ) { ... } * }, * // or * // link: { * // pre: function preLink(scope, iElement, iAttrs, controller) { ... }, * // post: function postLink(scope, iElement, iAttrs, controller) { ... } * // } * // or * // link: function postLink( ... ) { ... } * }; * return directiveDefinitionObject; * });
priority
當元素上面有多個指令時,指令的執行順序,數字越大優先級越高,越先執行。
terminal
告訴angular停止運行當前元素上比本指令優先級低的指令。
restrict
指令的調用方式
- 'E'-通過元素標籤調用 <self-directive></self-directive>
- 'A'-屬性調用<div self-directive></div>
- 'C'-類調用<div class='self-directive'></div>
- 'M'-註釋調用 <!-- directive: self-directive -->
template
可以有以下兩種形式:
- html文本,
- 函數,該函數可以接受兩個參數,tElement和tAttrs
templateUrl
可以有一下類型:
- 一個代表外部html文件路徑的字符串
- 一個可以接受兩個參數的函數,tElement和tAttrs,並返回一個外部html路徑道德字符串,對於加載過的模板angularjs會將它默認緩存到$templateCache服務中
replace
是否替換指令本省,默認爲false,如果設置了該參數,那麼指令本身會被指定的模板替代
scope
該參數有兩種形式
- 布爾值,可以被設置爲true,默認爲false,如果設置爲true,則會從父作用域繼承並創建一個新的作用域對象
- 隔離作用域,如果被設置爲一個對象,那麼指令內部會創建一個隔離的作用域,這樣模板無法直接訪問外部的作用域了,那麼有什麼方法可以讓內部的作用域同外界的作用域進行通信麼? 可以通過三種別名方式來同外部的作用域進行一個數據的綁定:
1.@或者@attr :通過@符號可以將本地的作用域同DOM屬性的值進行綁定 2.=或者=attr:通過=可以將本地作用域上的屬性值同父作用域上的屬性進行綁定
3.&或者&attr:通過&可以對父作用域進行綁定,以便在其中運行函數。
<input type="text" ng-model="to"/> <!-- 調用指令 --> <div scope-example ng-model="to" on-send="sendMail(email)" from-name="[email protected]" /> 在指令中我們可以這樣設置scope對象 scope: { ngModel: '=', // 將ngModel同指定對象綁定 onSend: '&', // 將引用傳遞給這個方法 fromName: '@' // 儲存與fromName相關聯的字符串 }
controller
可以設置爲一個字符串或者函數,如果是字符串則會在註冊的控制器中尋找對應的控制器。
也可以設置爲一個函數作爲控制器,可以給該控制器注入任何可以被注入的服務,除此之外有幾個特殊的服務可以被注入
$scope:與指令元素相關聯的當前作用域
$element:當前指令對應的元素
$attrs:當前元素屬性組成的對象
compile
compile可以設置爲一個對象或函數,其與link函數是互斥的,如果兩者同時設置,那麼link會被忽略。在compile函數中,我們可以對DOM進行操作,此時指令和實時數據還沒有被放置到DOM中,這個時候操作DOM性能消耗較低。
link
鏈接函數,其函數的簽名如下
link: function(scope, element, attrs, SomeController) { // 在這裏操作DOM,可以訪問required指定的控制器 }
scope:指令內部的作用域
iElement:使用指令的元素
iAttrs:元素的屬性
如果require選項提供了一個指令數據,那麼第四個參數會是一個由每個指令所對應的控制器組成的數組。