欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

AngularJS自定義控件實例詳解

 更新時間:2016年12月13日 11:24:13   作者:鄭浩-  
這篇文章主要介紹了AngularJS自定義控件,結(jié)合實例形式詳細(xì)分析了AngularJS自定義指令與模板操作的相關(guān)函數(shù)與使用技巧,需要的朋友可以參考下

本文實例講述了AngularJS自定義控件。分享給大家供大家參考,具體如下:

自定義指令介紹

AngularJS 指令作用是在 AngulaJS 應(yīng)用中操作 Html 渲染。比如說,內(nèi)插指令 ( {{ }} ), ng-repeat 指令以及 ng-if 指令。

當(dāng)然你也可以實現(xiàn)自己的。這就是 AngularJS 所謂的"教會 HTML 玩新姿勢”。本文將告訴你如何做到。

指令類型

可以自定義的指令類型如下:

元素
屬性
CSS class
Comment directives

這里面,AngularJS 強(qiáng)烈建議你用元素和屬性類型,而不用 CSS class 和 comment directives (除非迫不得已)。

指令類型決定了指令何時被激活。當(dāng) AngularJS 在 HTML 模板中找到一個 HTML 元素的時候,元素指令被激活。當(dāng) AngularJS 找到一個 HTML 元素屬性時,屬性指令被激活。當(dāng) AngularJS 找到一個 CSS class 時, CSS class 指令被激活,最后,當(dāng) AngularJS 找到 HTML comment 時,comment directive 被激活。

基礎(chǔ)例子

你可以向模塊注冊一個指令,像這樣:

<!-- lang: js -->
myapp = angular.module("myapp", []);
myapp.directive('div', function() {
  var directive = {};
  directive.restrict = 'E'; /* restrict this directive to elements */
  directive.template = "My first directive: {{textToInsert}}";
  return directive;
});

來看模塊中調(diào)用的 directive() 函數(shù)。當(dāng)你調(diào)用該函數(shù)時,意味著你要注冊一個新指令。directive() 函數(shù)的第一個參數(shù)是新注冊指令的名稱。這是之后你在 HTML 模板中調(diào)用它的時候用的名稱。例子中,我用了 'div' ,意思是說當(dāng) HTML 模板每次在找到 HTML 元素類型是 div 的時候,這個指令都會被激活。

傳遞給 directive 函數(shù)的第二個參數(shù)是一個工廠函數(shù)。調(diào)用該函數(shù)會返回一個指令的定義。 AngularJS 通過調(diào)用該函數(shù)來獲取包含指令定義的 JavaScript 對象。如果你有仔細(xì)看上面的例子,你會知道它返回的確是是一個 Javascript 對象。

這個從工廠函數(shù)中返回的 Javascript 對象有兩個屬性: restrict 和 template 字段。

restrict 字段用來設(shè)置指令何時被激活,是匹配到 HTML 元素時,還是匹配到元素屬性時。也就是指令類型。把restrict 設(shè)置為 E 時,只有名為 div 的 HTML 元素才會激活該指令。把 restrict 設(shè)置為 A 時,只有名為 div 的 HTML 元素屬性才會激活該指令。你也可以用 AE ,這樣會使得匹配到元素名和元素屬性名時,都可以激活該指令。

template 字段是一個 HTML 模板,用來替換匹配的 div 元素。它會把匹配到的 div 當(dāng)成一個占位符,然后用 HTML 模板在同一位置來替換掉它。也就是說,HTML 模板替換匹配的到 HTML 元素。

比如說你的 HTML 頁面有這樣一段 HTML:

<!-- lang: js -->
<div ng-controller="MyController" >
  <div>This div will be replaced</div>
</div>

當(dāng) AngularJS 找到內(nèi)嵌的 div 的時候,會激活自定義的指令。然后把該 div 元素替換掉,替換后的 HTML 將變成這樣:

<!-- lang: js -->
My first directive: {{textToInsert}}

然后你看到了,這段 HTML 里面包含了一個內(nèi)插指令 ({{textToInsert}})。AngularJS 會再執(zhí)行一次,讓內(nèi)插指令實際值顯示出來。然后 $scope.textToInsert 屬性將會在這個 HTML 點上替換掉內(nèi)插指令占位符。

template 和 templateUrl 屬性

創(chuàng)建自定義指令最簡單的例子就是上面這樣了。你的指令用來生成 HTML,然后你把 HTML 放到指令定義對象的 template 屬性中。下面這個例子是上面那最簡單的例子的重復(fù),注意 template部分:

<!-- lang: js -->
myapp = angular.module("myapp", []);
myapp.directive('div', function() {
  var directive = {};
  directive.restrict = 'E'; /* restrict this directive to elements */
  directive.template = "My first directive: {{textToInsert}}";
  return directive;
});

如果 HTML 模板越來越大,把它寫在一個 Javascript 字符串中肯定非常難維護(hù)。你可以把它放到一個單獨(dú)的文件中,然后 AngularJS 可以通過這個文件把它加載進(jìn)來。然后再把 HTML 模板文件的 URL 放到指令定義對象的 templateUrl 屬性中。下面是例子:

<!-- lang: js -->
myapp = angular.module("myapp", []);
myapp.directive('div', function() {
  var directive = {};
  directive.restrict = 'E'; /* restrict this directive to elements */
  directive.templateUrl = "/myapp/html-templates/div-template.html";
  return directive;
});

然后 AngularJS 會從 templateUrl 屬性中設(shè)置的 URL 將 HTML 模板加載進(jìn)來。

用獨(dú)立的 HTML 模板文件,設(shè)置 templateUrl 屬性,在你要創(chuàng)建更多的通用指令時會顯得更加有用,比如說用來顯示用戶信息的指令。例子:

<!-- lang: js -->
myapp = angular.module("myapp", []);
myapp.directive('userinfo', function() {
  var directive = {};
  directive.restrict = 'E'; /* restrict this directive to elements */
  directive.templateUrl = "/myapp/html-templates/userinfo-template.html";
  return directive;
});

例子創(chuàng)建了一個指令,當(dāng)AngularJS 找到一個 <userinfo> 元素的時候就會激活它。AngularJS 加載指向 /myapp/html-templates/userinfo-template.html 的模板并解析它,它就像從一開始就被嵌在上一級 HTML 文件中一樣。

從指令中隔離 $scope

在上面的例子中,把 userinfo 指令硬綁定到了 $scope ,因為 HTML 模板是直接引用 textToInsert 屬性的。直接引用 $scope 讓指令在同一個 controller 中的時候,非常難復(fù)用,因為 $scope在同一個 controller 中的值都是一樣的。比如說,你在頁面的 HTML 中這樣寫的時候:

<!-- lang: js -->
<userinfo></userinfo>
<userinfo></userinfo>

這兩個 <userinfo> 元素會被同樣的 HTML 模板取代,然后綁定到同樣的 $scope 變量上。結(jié)果就是兩個 <userinfo> 元素將會被一模一樣的 HTML 代碼給替換了。

為了把兩個 <userinfo> 元素綁定到 $scope 中的不同的值,你需要給 HTML 模板一個 isolate scope。

所謂 isolate scope 是綁定在指令上的獨(dú)立的 scope 對象。下面是定義的例子:

<!-- lang: js -->
myapp.directive('userinfo', function() {
  var directive = {};
  directive.restrict = 'E';
  directive.template = "User : {{user.firstName}} {{user.lastName}}";
  directive.scope = {
    user : "=user"
  }
  return directive;
})

請看 HTMl 模板中的兩個內(nèi)插指令 {{user.firstName}} 和 {{user.lastName}}。注意 user. 部分。以及directive.scope 屬性。 directive.scope 是個帶 user 屬性的 Javascript 對象。于是directive.scope 就成為了 isolate scope 對象,現(xiàn)在 HTML 模板被綁到了 directive.scope.user 上(通過 {{user.firstName}} 和 {{user.lastName}} 內(nèi)插指令)。

directive.scope.user 被設(shè)置為 “=user” 。意思是說 directive.scope.user 和 scope 中的屬性綁在一起的(不是 isolate scope),scope 中的屬性通過 user 屬性傳入 <userinfo> 元素。聽起來挺費(fèi)勁的,直接看例子:

<!-- lang: js -->
<userinfo user="jakob"></userinfo>
<userinfo user="john"></userinfo>

這兩個 <userinfo> 元素都有 user 屬性。user 的值指向了 $scope 中同名屬性,被指定的 $scope中的屬性將在 userinfo 的 isolate scope object 中被使用。

下面是完整的例子:

<!-- lang: js -->
<userinfo user="jakob"></userinfo>
<userinfo user="john"></userinfo>
<script>
myapp.directive('userinfo', function() {
  var directive = {};
  directive.restrict = 'E';
  directive.template = "User : <b>{{user.firstName}}</b> <b>{{user.lastName}}</b>";
  directive.scope = {
    user : "=user"
  }
  return directive;
});
myapp.controller("MyController", function($scope, $http) {
  $scope.jakob = {};
  $scope.jakob.firstName = "Jakob";
  $scope.jakob.lastName = "Jenkov";
  $scope.john = {};
  $scope.john.firstName = "John";
  $scope.john.lastName = "Doe";
});
</script>

compile() 和 link() 函數(shù)

如果你需要在你的指令中做更高級的操作,單純使用 HTML 模板做不到的時候,你可以考慮使用compile() 和 link() 函數(shù)。

compile() 和 link() 函數(shù)定義了指令如何修改匹配到的 HTML。

當(dāng)指令第一次被 AngularJS 編譯的時候 (在 HTML 中第一次被發(fā)現(xiàn)),compile() 函數(shù)被調(diào)用。compile() 函數(shù)將為該元素做一次性配置。

然后 compile() 函數(shù)以返回 link() 作為終結(jié)。link() 函數(shù)將在每次元素被綁到 $scope 數(shù)據(jù)時,都被調(diào)用。

下面是例子:

<!-- lang: js -->
<script>
myapp = angular.module("myapp", []);
myapp.directive('userinfo', function() {
  var directive = {};
  directive.restrict = 'E'; /* restrict this directive to elements */
  directive.compile = function(element, attributes) {
    // do one-time configuration of element.
    var linkFunction = function($scope, element, atttributes) {
      // bind element to data in $scope
    }
    return linkFunction;
  }
  return directive;
});
</script>

compile() 函數(shù)帶兩個參數(shù): element 和 attributes。

element 參數(shù)是 jqLite 包裝過的 DOM 元素。AngularJS 有一個簡化版 jQuery 可以用于操作 DOM,所以對 element 的 DOM 操作方式和你在 jQuery 中所知的一樣。

attributes 參數(shù)是包含了 DOM 元素中的所有的屬性集合的 Javascript 對象。因此,你要訪問某個屬性你可以這樣寫 attributes.type。

link() 函數(shù)帶三個參數(shù): $scope,element 和 attributes。element 和attributes 參數(shù)和傳到 compile() 函數(shù)中的一樣。$scope 參數(shù)是正常的 scope 對象,或者當(dāng)你在指令定義對象中定義了 isolate scope 的時候,它就是 isolate scope。

compile() 和 link() 的命名相當(dāng)混亂。它們肯定是受編譯隊伍的啟發(fā)而命名的。我可以看到相似點,不過一個編譯器是傳入一次,然后輸出。而指令則是配置一次 HTML 元素,然后在之后的 $scope 對象改變時進(jìn)行更新。

compile() 函數(shù)如果叫做 create(), init() 或者 configure()也許會更好。這樣可以表達(dá)出這個函數(shù)只會被調(diào)用一次的意思。

而 link() 函數(shù)如果叫 bind() 或者 render() 也許會更好,能更好的表達(dá)出這樣的意思,在指令綁定數(shù)據(jù)或者重綁定數(shù)據(jù)的時候,這個函數(shù)將會被調(diào)用。

下面是一個完整的例子,演示了指令使用 compile() 和 link() 函數(shù)的:

<!-- lang: js -->
<div ng-controller="MyController" >
  <userinfo >This will be replaced</userinfo>
</div>
<script>
  myapp = angular.module("myapp", []);
  myapp.directive('userinfo', function() {
    var directive = {};
    directive.restrict = 'E'; /* restrict this directive to elements */
    directive.compile = function(element, attributes) {
      element.css("border", "1px solid #cccccc");
      var linkFunction = function($scope, element, attributes) {
        element.html("This is the new content: " + $scope.firstName);
        element.css("background-color", "#ffff00");
      }
      return linkFunction;
    }
    return directive;
  })
  myapp.controller("MyController", function($scope, $http) {
    $scope.cssClass = "notificationDiv";
    $scope.firstName = "Jakob";
    $scope.doClick = function() {
      console.log("doClick() called");
    }
  });
</script>

compile() 函數(shù)設(shè)置 HTML 元素的 border 。它只執(zhí)行一次,因為 compile() 函數(shù)只執(zhí)行一次。

link() 替換 HTML 元素內(nèi)容,并且把背景顏色設(shè)置為黃色。

把設(shè)置 border 放在 compile(), 把背景顏色放在 link() 沒啥特別的理由。你可以把所有的操作都丟到 compile(),或者都放到 link()。如果都放到 compile() 它們只會被設(shè)置一次(你需要它們是常量的話)。如果放到了 link(),它們會在每次 HTML 元素被綁到 $scope 的時候都發(fā)生變化。當(dāng)你希望根據(jù) $scope 中的數(shù)據(jù)來設(shè)置 boarder 和背景顏色的時候這非常有用。

只設(shè)置 link() 函數(shù)

有時候你的指令可能不需要 compile() 。你只需要用到 link()。這種情況下,你可以直接設(shè)置指令定義對象中的 link() 函數(shù)。下面是一個對上面例子的修改,只用 link 函數(shù):

<!-- lang: js -->
<div ng-controller="MyController" >
  <userinfo >This will be replaced</userinfo>
</div>
<script>
  myapp = angular.module("myapp", []);
  myapp.directive('userinfo', function() {
    var directive = {};
    directive.restrict = 'E'; /* restrict this directive to elements */
    directive.link = function($scope, element, attributes) {
        element.html("This is the new content: " + $scope.firstName);
        element.css("background-color", "#ffff00");
    }
    return directive;
  })
  myapp.controller("MyController", function($scope, $http) {
    $scope.cssClass = "notificationDiv";
    $scope.firstName = "Jakob";
    $scope.doClick = function() {
      console.log("doClick() called");
    }
  });
</script>

注意 link() 方法和之前例子中返回的 link() 是完全一樣的。

通過 Transclusion 封裝元素的指令

到目前為止,我們看到的所有例子,都是把匹配到的元素內(nèi)容給替換為指令的指定內(nèi)容,不管是通過 Javascript 也好或者 HTML 模板也好。不過如果遇到內(nèi)容中有部分是開發(fā)者可以指定的內(nèi)容的時候呢?比如說:

<!-- lang: js -->
<mytransclude>This is a transcluded directive {{firstName}}</mytransclude>

標(biāo)記為 <mytransclude> 的元素,它的部分內(nèi)容可以由開發(fā)者設(shè)置。因此,這部分 HTML 不應(yīng)該被指令的 HTML 模板給替換。我們實際上是希望這部分 HTML 由 AngularJS 來處理的。這個處理叫做 “transclusion”。 1

為了能讓 AngularJS 把這部分 HTML 放到指令內(nèi)部處理,你必須設(shè)置指令定義對象的 transclude 屬性為 true。你還需要告訴 AngularJS,指令的 HTML 模板中哪一部分需要把 transcluded HTML 包含進(jìn)來。你可以通過插入 ng-transclude 屬性 (實際上,是一個指令) 到 HTML 模板的 HTML 元素中,標(biāo)記你想要添加 transcluded HTML 的元素。

下面是一個 AngularJS 指令,演示如何使用 transclusion:

<!-- lang: js -->
<mytransclude>This is a transcluded directive {{firstName}}</mytransclude>
<script>
  myapp = angular.module("myapp", []);
  myapp.directive('mytransclude', function() {
    var directive = {};
    directive.restrict = 'E'; /* restrict this directive to elements */
    directive.transclude = true;
    directive.template = "<div class='myTransclude' ng-transclude></div>";
    return directive;
  });
  myapp.controller("MyController", function($scope, $http) {
    $scope.firstName = "Jakob";
  });
</script>

注意 <mytransclude> 元素內(nèi)的 HTML。這部分 HTML 代碼包含了內(nèi)插指令 {{firstName}}。我們希望 AngularJS 來為我們處理這部分 HTML,讓內(nèi)插指令執(zhí)行。為了實現(xiàn)這個目的,我在指令定義對象中把 transclude 設(shè)置為 true。我還在 HTML 模板中用到了 ng-transclude 屬性。這個屬性告訴 AngularJS 什么元素需要插入到 transcluded HTML。

1: 說實話,我沒看懂那個定義,說的太TM難懂了,而且我好不爽寫代碼沒輸出的教程。只好自己動手做做例子。我覺得其實應(yīng)該是這樣的,把目標(biāo)元素內(nèi)容作為一個整體,拿到 HTML 模板中來,添加到 ng-transclude 指定的標(biāo)簽下。這個處理,我覺得應(yīng)該就是叫做 transcluded。比如說剛才的例子(有些 bug,自己修正一下),因為 directive.transclude = true; ,所以原來 <mytransclude> 元素內(nèi)的 HTML:

<!-- lang: js -->
This is a transcluded directive {{firstName}}

在激活指令 'mytransclude' 的時候,會被拿到 'mytransclude' 指令的模板中來,放到被 ng-transclude 指定的

<!-- lang: js -->
"<div class='myTransclude' ng-transclude></div>"

中。于是最終輸出的結(jié)果應(yīng)該是:

<!-- lang: js -->
<mytransclude>
  <div class='myTransclude' ng-transclude>
    <span class="ng-scope ng-binding">This is a transcluded directive Jakob</span>
  </div>
</mytransclude>

更多關(guān)于AngularJS相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《AngularJS入門與進(jìn)階教程》及《AngularJS MVC架構(gòu)總結(jié)

希望本文所述對大家AngularJS程序設(shè)計有所幫助。

相關(guān)文章

最新評論