1. 程式人生 > >angularJS中如何寫自定義指令

angularJS中如何寫自定義指令

module ren gif 發送郵件 www amp 提前 ras instance

指令定義 (轉自http://www.cnblogs.com/huangshikun/p/7060787.html)

  • 對於指令,可以把它簡單的理解成在特定DOM元素上運行的函數,指令可以擴展這個元素的功能
  • 例如,ng-click可以讓一個元素能夠監聽click事件,並在接收到事件的時候執行angularJS表達式
  • 正是指令使得angularJS這個框架變得強大,並且正如所見,我們可以自己創造新的指令

指令聲明方法

技術分享 技術分享
angular.module(‘freefedApp‘,[]).directive(name,function(){
      return {
            restrict: String,
            priority: Number,
            terminal: Boolean,
            template: String or Template Function:function(tElement, tAttrs) (...},
            templateUrl: String,
            replace: Boolean or String,
            scope: Boolean or Object,
            transclude: Boolean,
            controller: String orfunction(scope, element, attrs, transclude, otherInjectables) { ... }, 
            controllerAs: String,
            require: String,
            link: function(scope, iElement, iAttrs) { ... },
       };
});
技術分享 技術分享

指令作用域

DOM中每個指令調用時都可能會:

  • 直接調用相同的作用域對象
  • 從當前作用域對象繼承一個新的作用域對象
  • 創建一個同當前作用域相隔離的作用域對象

作用域scope設置(參數是可選的,默認值是false):

  • true 會從父作用域繼承並創建一個新的作用域對象
  • false 直接調用相同作用域對象
  • {} 創建具有隔離作用域,具有隔離作用域的指令最主要的使用場景是創建可復用的組件,組件可以在未知上下文中使用,並且可以避免汙染所處的外部作用域或不經意地汙染內部作用域

作用域綁定策略

對於指令隔離作用域angularJS提供了幾種方法能夠將指令內部的隔離作用域,同指令外部的作用域進行數據綁定

  • @(or @attr) 使用@符號將指令本地作用域同DOM屬性的值進行綁定,指令內部作用域可以使用外部作用域的變量,純粹的值綁定
  • =(or =attr) 通過=可以將本地作用域上的屬性同父級作用域上的屬性進行雙向的數據綁定,就像普通的數據綁定一樣,本地屬性會反映出父數據模型中所發生的改變
  • &(or &attr) 通過&符號可以對父級作用域進行綁定,以便在其中運行函數。意味著對這個值進行設置時會生成一個指向父級作用域的包裝函數,要使調用帶有一個參數的父方法,我們需要傳遞一個對象,這個對象的鍵是參數的名稱,值是要傳遞給參數的內容
技術分享 技術分享
demo.html

<!doctype html>
<html ng-app="freefedApp">
   <head>
        <title>angular應用demo</title>
        <script src="angular.js"></script>
        <script src="app.js"></script>
  </head>
  <body>
  <div ng-controller="freefedCtrl">
       發送郵件地址 : <input type="text" ng-model="from" />
       接收郵件地址 : <input type="text" ng-model="to" />
        <div email-directive from-email="{{from}}" to-email="to" on-send="sendMail(email)">
        </div>
   </div>
  </body>
</html>
技術分享 技術分享

技術分享 技術分享
app.js

/*聲明module*/
var module = angular.module(‘freefedApp‘,[]);

/*聲明控制器*/
module.controller(‘freefedCtrl‘,[‘$scope‘,function($scope){
      $scope.from = ‘[email protected]‘;
      $scope.sendMail = function(email){
          alert(‘我將發送郵件到‘ + email);
      };
}]);

/*聲明指令*/
module.directive(‘emailDirective‘,function(){
      return {
           scope : {
               fromEmail : ‘@‘       //值綁定
               toEmail : ‘=‘         //和父級作用域屬性進行雙向綁定
               onSend : ‘&‘          //與父級作用域進行綁定
           },
           link : function( scope,el,attr ){
                scope.onSend( { email : scope. toEmail} );      //調用與onSend綁定的父級作用域的sendMail函數,並傳遞參數email的值給它
           }
      };
});
技術分享 技術分享

指令參數詳解

  • restrict: String
    restrict是一個可選的參數。它告訴angularJS這個指令在DOM中可以何種形式被聲明。默
    認angularJS認為restrict的值是A,即以屬性的形式來進行聲明;可選值如下:
    E(元素)
    A(屬性,默認值)
    C(類名)
    M(註釋)
  • priority: Number,
    優先級參數可以被設置為一個數值。大多數指令會忽略這個參數,使用默認值0,但也有些 場景設置高優先級是非常重要甚至是必須的。
    例如,ngRepeat將這個參數設置為1000,這樣就可 10 以保證在同一元素上,它總是在其他指令之前被調用
  • terminal: Boolean,

    這個參數用來告訴angularJS停止運行當前元素上比本指令優先級低的指令。但同當前指令 優先級相同的指令還是會被執行。
    ?如果元素上某個指令設置了terminal參數並具有較高的優先級,就不要再用其他低優先級的 指令對其進行修飾了,因為不會被調用。
    但是具有相同優先級的指令還是會被繼續調用。使用了terminal參數的例子是ngView和ngIf。ngIf的優先級略高於ngView,如果ngIf的表 達式值為true,
    ngView就可以被正常執行,但如果ngIf表達式的值為false,由於ngView的優先 級較低就不會被執行
  • template: String or Template Function:function(tElement, tAttrs) (...},

    template參數是可選的,必須被設置為以下兩種形式之一:
    一段HTML文本;
    一個可以接受兩個參數的函數,參數為tElement和tAttrs,並返回一個代表模板的字符
    串。tElement和tAttrs中的t代表template,是相對於instance的。在討論鏈接和編譯 設置時會詳細介紹,模板元素或屬性與實例元素或屬性之間的區別。
    angularJS會同處理HTML一樣處理模板字符串。模板中可以通過大括號標記來訪問作用域, 例如{{ expression }}。
    如果模板字符串中含有多個DOM元素,或者只由一個單獨的文本節點構成,那它必須被包 含在一個父元素內。換句話說,必須存在一個根DOM元素:
         template: ‘         <div> <-- single root element -->             <a href="http://google.com">Click me</a>             <h1>When using two elements, wrap them in a parent element</h1>         </div>另外,註意每一行末尾的反斜線,這樣angularJS才能正確解析多行字符串。在實際生產中, 更好的選擇是使用templateUrl參數引用外部模板
  • templateUrl: String,

    templateUrl是可選的參數,可以是以下類型:
    一個代表外部HTML文件路徑的字符串;
    一個可以接受兩個參數的函數,參數為tElement和tAttrs,並返回一個外部HTML文件路徑的字符串,
    默認情況下,調用指令時會在後臺通過Ajax來請求HTML模板文件
    模板加載是異步的,意味著編譯和鏈接要暫停,等待模板加載完成。
    通過Ajax異步加載大量的模板將嚴重拖慢一個客戶端應用的速度。為了避免延遲,可以在部 署應用之前對HTML模板進行緩存。
    在大多數場景下緩存都是一個非常好的選擇,
    因為angularJS 通過減少請求數量提升了性能。模板加載後,angularJS會將它默認緩存到$templateCache服務中。
    在實際生產中,可以提前將模板緩存到一個定義模板的JavaScript文件中,這樣就不需要通過XHR來加載模板了
  • replace: Boolean or String,

    replace是一個可選參數,如果設置了這個參數,值必須為true,因為默認值為false。
    默認值意味著模板會被當作子元素插入到調用此指令的元素內部:
         <div some-directive></div>
         .directive(‘someDirective‘, function() {
                 return {
                      template: ‘<div>some stuff here<div>‘
                 }; 
          });
    調用指令之後的結果如下(這是默認replace為false時的情況):
         <div some-directive>
             <div>some stuff here<div>
         </div> 如果replace被設置為了true:
         .directive(‘someDirective‘, function() {
                 return {
                      replace: true // 修飾過
    ??????                  template: ‘<div>some stuff here<div>‘
                 }; 
         ?});
    指令調用後的結果將是:
         <div>some stuff here<div>
  • scope: Boolean or Object,

    看上面指令作用域
  • transclude: Boolean,

  • controller: String orfunction(scope, element, attrs, transclude, otherInjectables) { ... },

    controller參數可以是一個字符串或一個函數。當設置為字符串時,會以字符串的值為名字, 
    來查找註冊在應用中的控制器的構造函數</pre>
    * controllerAs: String,<pre>controllerAs參數用來設置控制器的別名,可以以此為名來發布控制器,我們可以在路由和指令中創建匿名控制器的強大 能力。
    這種能力可以將動態的對象創建成為控制器,並且這個對象是隔離的、易於測試的```
  • require: String,
  • link: function(scope, iElement, iAttrs) { ... },

    用link函數創建可以操作DOM的指令

angularJS中如何寫自定義指令