angularjs 指令詳解 - template, restrict, replace


通過指令機制,angularjs 提供了一個強大的擴展系統,我們可以通過自定義指令來擴展自己的指令系統。

怎樣定義自己的指令呢?

我們通過 Bootstrap UI 來學習吧。這個項目使用 angularjs 將 Bootstrap 3 進行了封裝,是我們學習 angularjs 很好的樣例。

從 Alert 開始

首先,我們從比較簡單的 alert 指令來開始學習。

在 Bootstrap 中,警告框使用類 alert 來表示, 通過 alert-success, alert-info, alert-warning, alert-danger 來表示不同類型的警告。

<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">&times;</button>
  <strong>Warning!</strong> Best check yo self, you're not looking too good.
</div>

bootstrap UI 中的用法

在 Bootstrap UI 的示例中,我們可以直接通過自定義的 alert 來定義一個提示。其中的 type 用來定義提示的類型,提示的信息內容通過綁定來處理。

<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);
  };

}

bootstrap UI 中的定義

下面就是指令的定義了。

 

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: '&'
    }
  };
});

最終生成的標記為:

<div ng-controller="AlertDemoCtrl" class="ng-scope">
    <!-- ngRepeat: alert in alerts -->
    <div class="alert ng-isolate-scope alert-danger" ng-class="&quot;alert-&quot; + (type || &quot;warning&quot;)" 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="&quot;alert-&quot; + (type || &quot;warning&quot;)" 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 的取值可以有三種:

  • A 用於元素的 Attribute,這是默認值
  • E 用於元素的名稱
  • C 用於 CSS 中的 class

比如說,我們這樣定義指令。

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>

 

transclusion 嵌入

如果我們在上面的元素中這么寫會怎樣呢?

<!-- 元素 -->
<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>

 

看看 alert 使用的模版

模版的實際定義如下。

<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">&times;</span>
        <span class="sr-only">Close</span>
    </button>
    <div ng-transclude></div>
</div>

 在生成之后,alert 被替換為了 div 元素,至於關閉按鈕是否顯示出來,取決於 closeable 屬性的值。

 replace 定義為真,表示使用模版的定義替換原來的元素,而 transclude 用來把內容填充到目標位置。在內嵌的 div 元素中使用了 ng-transclude 指示了填充的目標位置。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM