經過指令機制,angularjs 提供了一個強大的擴展系統,咱們能夠經過自定義指令來擴展本身的指令系統。html
怎樣定義本身的指令呢?git
咱們經過 Bootstrap UI 來學習吧。這個項目使用 angularjs 將 Bootstrap 3 進行了封裝,是咱們學習 angularjs 很好的樣例。angularjs
首先,咱們從比較簡單的 alert 指令來開始學習。github
在 Bootstrap 中,警告框使用類 alert 來表示, 經過 alert-success, alert-info, alert-warning, alert-danger 來表示不一樣類型的警告。bootstrap
<div class="alert alert-success">...</div> <div class="alert alert-info">...</div> <div class="alert alert-warning">...</div> <div class="alert alert-danger">...</div>
對於可關閉的警告框來講,還能夠用一個可選的.alert-dismissable和關閉按鈕,可是,這是經過腳原本實現的,在 bootstrap ui 這裏沒有使用。瀏覽器
<div class="alert alert-warning alert-dismissable"> <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button> <strong>Warning!</strong> Best check yo self, you're not looking too good. </div>
在 Bootstrap UI 的示例中,咱們能夠直接經過自定義的 alert 來定義一個提示。其中的 type 用來定義提示的類型,提示的信息內容經過綁定來處理。app
<div ng-controller="AlertDemoCtrl"> <alert ng-repeat="alert in alerts" type="alert.type" close="closeAlert($index)">{{alert.msg}}</alert> <button class='btn btn-default' ng-click="addAlert()">Add Alert</button> </div>
對應的腳本函數
function AlertDemoCtrl($scope) { $scope.alerts = [ { type: 'danger', msg: 'Oh snap! Change a few things up and try submitting again.' }, { type: 'success', msg: 'Well done! You successfully read this important alert message.' } ]; $scope.addAlert = function() { $scope.alerts.push({msg: "Another alert!"}); }; $scope.closeAlert = function(index) { $scope.alerts.splice(index, 1); }; }
下面就是指令的定義了。學習
angular.module('ui.bootstrap.alert', []) .controller('AlertController', ['$scope', '$attrs', function ($scope, $attrs) { $scope.closeable = 'close' in $attrs; }]) .directive('alert', function () { return { restrict:'EA', controller:'AlertController', templateUrl:'template/alert/alert.html', transclude:true, replace:true, scope: { type: '@', close: '&' } }; });
最終生成的標記爲:ui
<div ng-controller="AlertDemoCtrl" class="ng-scope"> <!-- ngRepeat: alert in alerts --> <div class="alert ng-isolate-scope alert-danger" ng-class=""alert-" + (type || "warning")" ng-repeat="alert in alerts" type="alert.type" close="closeAlert($index)"> <button ng-show="closeable" type="button" class="close" ng-click="close()">×</button> <div ng-transclude=""><span class="ng-scope ng-binding">Oh snap! Change a few things up and try submitting again.</span></div> </div> <!-- end ngRepeat: alert in alerts --> <div class="alert ng-isolate-scope alert-success" ng-class=""alert-" + (type || "warning")" ng-repeat="alert in alerts" type="alert.type" close="closeAlert($index)"> <button ng-show="closeable" type="button" class="close" ng-click="close()">×</button> <div ng-transclude=""><span class="ng-scope ng-binding">Well done! You successfully read this important alert message.</span></div> </div><!-- end ngRepeat: alert in alerts --> <button class="btn btn-default" ng-click="addAlert()">Add Alert</button> </div>
看不懂!沒有關係,咱們慢慢來。
從模版開始
好比說,在下面的代碼中,你但願經過 my-customer 將一個內容爲空白的 div 變成內容爲綁定名字和地址的文本內容
<div ng-controller="Ctrl"> <div my-customer></div> </div>
好比生成下面的結果:
<div ng-controller="Ctrl"> <div>Name: {{customer.name}} Address: {{customer.address}}</div> </div>
對於以上的要求,咱們能夠定義一個名爲 my-customer 的指令。而後,說明這個指令將會生成元素中間的內容,咱們稱之爲模版的內容。
angular.module('docsSimpleDirective', []) .controller('Ctrl', function($scope) { $scope.customer = { name: 'Naomi', address: '1600 Amphitheatre' }; }) .directive('myCustomer', function() { return { template: 'Name: {{customer.name}} Address: {{customer.address}}' }; });
directive 表示咱們要定義一個自定義的指令,指令的名稱爲 myCustomer,後面的函數用來定義指令的特徵
template 表示咱們的指令使用的模版,你會看到,它的值就是咱們準備生成的內容。
不過,你會說,且慢,我但願使用 myCustomer 元素,而不是 Attribute ,那又該怎麼辦呢?
默認狀況下,指令只能做爲元素的 attribute 使用,若是但願用在其它的地方,那麼你須要學習第二個屬性 restrict
restrict 的取值能夠有三種:
好比說,咱們這樣定義指令。
var app = angular.module("app", []) .directive("hello", function () { var option = { restrict: "AEC", template: "Hello, Directive", }; return option; })
因爲咱們指定了能夠用於三種狀況下,那麼,就能夠以下三種形式來使用這個指令
<!-- 元素 --> <div> <hello></hello> </div> <!-- 屬性--> <div> <div hello></div> </div> <!-- class --> <div> <div class="hello"></div> </div>
輸出的結果分別以下:
<!-- 元素 --> <div> <hello>Hello, Directive</hello> </div> <!-- 屬性--> <div> <div hello="">Hello, Directive</div> </div> <!-- class --> <div> <div class="hello">Hello, Directive</div> </div>
下一個你須要知道的參數爲 replace,顧名思義,這是替換的意思,默認爲 false,就是將模版的內容追加到元素中,若是設置爲 true,那麼模版的內容將會替換元素的內容。
原來的輸出將會成爲下面的樣子,實際上,你在頁面中將會看不到輸出的內容,hello 元素瀏覽器是不認識的,而其它兩種方式,咱們又沒有生成任何的元素。
<!-- 元素 --> <div> <hello></hello> </div> <!-- 屬性--> <div> <div hello=""></div> </div> <!-- class --> <div> <div class="hello"></div> </div>
若是咱們將模版更新爲一個元素,以下所示。
var app = angular.module("app", []) .directive("hello", function () { var option = { restrict: "AECM", template: "<h3>Hello, Directive</h3>", replace: true }; return option; })
此次,你將會看到在 replace 爲 true 狀況下的元素了。
<!-- 元素 --> <div> <h3>Hello, Directive</h3> </div> <!-- 屬性--> <div> <h3 hello="">Hello, Directive</h3> </div> <!-- class --> <div> <h3 class="hello">Hello, Directive</h3> </div>
若是咱們在上面的元素中這麼寫會怎樣呢?
<!-- 元素 --> <div> <hello>12345678</hello> </div>
你會發現 12345678 消失了,這個元素徹底被模版替換了。若是咱們須要保留這些內容怎麼處理呢?
transclusion 指的是定義模版的元素如何處理問題,好比,在使用指令的時候,指令中包含了內容,那麼這些內容咱們是否直接被替換爲模版,仍是將這些內容嵌入到模版中。
在使用它的時候,須要在兩個地方說明,一是在指令中說明須要嵌入,二是在模版中說明嵌入到哪裏。
var app = angular.module("app", []) .directive("hello", function () { var option = { restrict: "AECM", template: "<h3>Hello, Directive, <span ng-transclude></span></h3>", replace: true, transclude: true }; return option; })
而後,在模版中說明嵌入的位置。
template: "<h3>Hello, Directive, <span ng-transclude></span></h3>",
頁面中的使用。
<hello>12345678</hello>
最後,生成的結果以下。
<h3>Hello, Directive, <span ng-transclude=""><span class="ng-scope">12345678</span></span></h3>
模版的實際定義以下。
<div class="alert" ng-class="{'alert-{{type || 'warning'}}': true, 'alert-dismissable': closeable}" role="alert"> <button ng-show="closeable" type="button" class="close" ng-click="close()"> <span aria-hidden="true">×</span> <span class="sr-only">Close</span> </button> <div ng-transclude></div> </div>
在生成以後,alert 被替換爲了 div 元素,至於關閉按鈕是否顯示出來,取決於 closeable 屬性的值。
replace 定義爲真,表示使用模版的定義替換原來的元素,而 transclude 用來把內容填充到目標位置。在內嵌的 div 元素中使用了 ng-transclude 指示了填充的目標位置。