angular自定義指令詳解

指令(directive)是angular裏面最核心也是最難懂的東西,在慕課網看了下大漠窮秋老溼的視頻,本身百度半天作了一些小test,總算把一切都搞明白了。html

先列出學習來源:angularjs

指令中controller和link的區別:http://www.cnblogs.com/CreateMyself/p/5568202.htmlbootstrap

 

angular視頻教程:http://www.imooc.com/learn/156app

 

指令中的隔離 Scope :https://blog.coding.net/blog/angularjs-directive-isolate-scope框架

 

angular學習筆記:https://www.zouyesheng.com/angular.html#toc68dom

 

 

1、指令的建立:

首先你得先建立一個module:ionic

var module1 = angular.module('module1',[]);
angular.bootstrap(document.body,['module1']);

而後你還得有一個對應的controller:函數

var module1 = angular.module('module1',[]);

module1.controller('ctl1', function($scope) {
   $scope.content = 'i\'m, module 1';
    $scope.name = 'module1';
    $scope.save = function() {
        console.log('is function save');
    };
});
angular.bootstrap(document.body,['module1']);
 

 

 

而後你就能夠安心的建立指令了:學習

// 銜接上面的代碼
m1.directive('testDirective', function() { // 將對象return出去 return{ restrict: 'E',// 指令類型 E:element A:attribute M:comment C: class template: '<div>我是指令生成的內容</div>'; replace: true, //使用模板替換原始標記 指令內本來的數據將被清空 } });
angular.bootstrap(document.body,['module1']);
 

對應的html能夠這樣寫:ui

<body>
    <div  ng-controller="ctl1">{{content}}
        <test-directive>這是本來的內容</test-directive>
    </div>
</body>

以上代碼須要注意一下幾點:

1.咱們定義的指令名稱是testDirective,可是在html中要寫成test-directive。

2.咱們把指令裏面的代碼都放在了function中的return裏面,其實return出去的內容就是整個指令對象。

3.angular.bootstrap(document.body,['module1']);至關於咱們在html中使用ng-app指令。推薦使用bootstarp而不是ng-app;

 

 

2、指令的屬性

指令的屬性以下:

  • name
  • priority
  • terminal
  • scope
  • controller
  • require
  • restrict
  • template
  • templateUrl
  • replace
  • transclude
  • compile
  • link

其中的name、priority、terminal不作詳細的介紹。

name就是指令名,對應上面代碼中的testDirective,priority多個指令設置在同一個元素上的執行優先級,執行順序從低至高:1>2>3.priority的值爲正整數,好比priority: 1,

terminal, true/false 若是爲true,同一個元素上的其餘指令的優先級高於本指令,其餘指令將中止執行

priority和terminal傳送門

1.restrict屬性

angular內置的一些指令,好比ng-app,ng-click之類的,都是以html元素的屬性(atrrbile)的形式來實現的,我在使用ionic框架的時候,裏面有不少自定義的標籤、好比:<ion-content></ion-content>。這也是一個指令,他是經過html元素(element)來實現的。除了這兩個以外,指令還支持class(html標籤的class屬性)、commment(html中的註釋)來實現。

在JS代碼中,restrict能夠有如下賦值:

 restrict: 'AE',// 指令類型  E:element A:attribute M:comment C: class

能夠是多個restrict: 'AEMC',也能夠是一個restrict: 'E'。在html中對應的寫法爲:

其中註釋: <!-- 兩邊必定要留空格,否則什麼都不會發生 -->

 

 

 

 

2.template和templateUrl

同一個指令中只能templatetemplateUrl只能選其一。

template爲模板內容。即你要在指令所在的容器中插入的html代碼。

template屬性接收一個字符串,相似這樣:

  template: '<div>我是指令生成的內容</div>';

 

你也能夠將整個template寫得很複雜,可是,複雜的代碼很是不易維護。而且你還得換行,得用字符串拼接每一行。

當你的tamplate超出10行就會顯得辣眼睛,過長的template建議使用templateUrl代替。

 

 

templateUrl爲從指定地址獲取模板內容。即你要在指令所在的容器中插入的一個.html文件。

有了templateUrl咱們就能夠將想實現的內容寫成一個單獨的html模版,在須要的地方插入,使用起來會很舒服。

這裏的templateUrl相似於JSP中的include,angular也有一個ng-include指令。

具體的詳細請點鏈接:http://www.ziqiangxuetang.com/angularjs/angularjs-include.html

 

 

3.replace和transclude

replace:是否用模板替換當前元素。true : 將指令標籤替換成temple中定義的內容,頁面上不會再有<my-directive>標籤;false :則append(追加)在當前元素上,即模板的內容包在<my-directive>標籤內部。默認false。

transculde:是否使用ng-transculde來包含html中指令包含的原有的內容,接收兩個參數true/false

先上例子:replace

var app = angular.module("app", [])
    .directive("hello", function () {
        var option = {
            restrict: "AECM",
            template: "<h3>Hello, Directive</h3>",
            replace: true  //這裏replace爲true,因此原來的內容會被template代替
        };
        return option;
    })
<html>
    <head></head>
    <body>
        <hello>我是原來的內容</hello> ===> 變成<h3>Hello, Directive</h3>
      若是replace爲false ===><hello><h3>Hello, Directive</h3></hello>
</body> 
</html>

transclude:

var app = angular.module("app", [])
    .directive("hello", function () {
        var option = {
            restrict: "AECM",
            template: "<h3>Hello, Directive</h3><span ng-transclude></span>",
            transculde: true  //這裏transculde爲true,因此原來的內容會被放在有ng-transclude屬性的標籤內
        };
        return option;
    })
<html>
    <head></head>
    <body>
        <hello>我是原來的內容</hello> ===> 變成<hello><h3>Hello, Directive</h3><span ng-transclude>我是原來的內容</span></hello>
</body> 
</html>

 

4.指令中的scope

directive 默認能共享父 scope 中定義的屬性,例如在模版中直接使用父 scope 中的對象和屬性。一般使用這種直接共享的方式能夠實現一些簡單的 directive 功能。

可是,當你要建立一個能夠重複使用的directive的時候,就不能依賴於父scope了,由於在不一樣的地方使用directive對應的父scope不同。

因此你須要一個隔離的scope,咱們能夠向下面這樣來定義咱們的scope。

module1.directive("testDirective", function () {
        return {
            scope: {
                value: '提莫隊長正在待命!'
                         },
            template: 'Say:{{value}}'
        }
});             

這樣就很方便的將咱們directive的上下文scope給定義出來了,可是,若是我想將父scope中的屬性傳遞給directive的scope怎麼辦呢?

directive 在使用隔離 scope 的時候,提供了三種方法同隔離以外的地方交互:

  • @ 綁定一個局部 scope 屬性到當前 dom 節點的屬性值。結果老是一個字符串,由於 dom 屬性是字符串。
  • & 提供一種方式執行一個表達式在父 scope 的上下文中。若是沒有指定 attr 名稱,則屬性名稱爲相同的本地名稱。
  • = 經過 directive 的 attr 屬性的值在局部 scope 的屬性和父 scope 屬性名之間創建雙向綁定。

以上三種方式都要在directive的attr屬性中進行賦值。上面的話理解起來比較困難,我根據本身的理解作了一下修改:

@:只能綁定字符串,因此一些簡單的繼承父scope的屬性使用@
=: 須要實現雙向數據綁定的時候使用=
&: 提供一種方式執行一個表達式在父scope的上下文中,即便用於將父scope中的函數綁定在指令的scope中

以上的理解也許有些偏頗,歡迎指正。

(1)先說@

app.controller("ctl1", function ($scope) {
        $scope.name = "hello world";
    }).directive("testDirective", function () {
        return {
            scope: {
                name: "@"
            },
            template: 'Say:{{name}} <br>改變隔離scope的name:<input type="buttom" value="" ng-model="name" class="ng-pristine ng-valid">'
        }
})
<div ng-controller="ctl1">
   <div>
       <div>父scope:
           <div>Say:{{name}}<br>改變父scope的name:<input type="text" value="" ng-model="name"/></div>
       </div>
       <div>隔離scope:這個顯示爲hello world
           <div test-directive name="{{name}}"></div>
       </div>
        <div>隔離scope(不使用{{name}}這個就直接顯示爲name了):
             <div test-directive name="name"></div> 
         </div>
   </div>

咱們在test-directive指令所在的div上面,增長了一個name屬性,要使用雙花括號來給屬性賦值。也能夠寫成nameCopy:'@nameForCtl',這樣寫,在給directive中的scope的屬性賦值的時候,獲取查詢@後面的name這個標識對應的屬性的值(這裏nameForCtl在js中是駝峯寫法,一樣的在html中對應的屬性名應該寫成name-for-ctl)。不是很推薦這種寫法,感受有點多餘。

(2)=

上一個例子中,咱們使用name="{{name}}"的形式來傳遞父scope 的屬性對應的值,so,咱們只是把對應的值傳遞給了directive的scope,當我想實如今directive中改變父scope傳遞過來的值時,父scope中的值也對應的改變,顯然用@這種方法走不通。

這時=就派上用場了。

 app.controller("ctl1", function ($scope) {
        $scope.user = {
            name: 'hello',
            id: 1
        };
    }).directive("testDirective", function () {
        return {
            scope: {
                user: "="
            },
            template: 'Say:{{user.name}} <br>改變隔離scope的name:<input type="buttom" value="" ng-model="user.name"/>'
        }
    })
<div ng-controller="ctl1">
    <div>父scope:
        <div>Say:{{user.name}}<br>改變父scope的name:<input type="text" value="" ng-model="user.name"/></div>
    </div>
    <div>隔離scope:
        <div isolated-directive user="user"></div>
    </div>
    <div>隔離scope(使用{{name}},這個會報錯):
        <div isolated-directive user="{{user}}"></div> 
    </div>
</div>

這一個例子和上一個例子不一樣的地方就是屬性賦值的時候,一個應該使用{{}},一個不應使用。=爲了實現雙向數據綁定,angular會使用‘=’對應的屬性的值與父scope中的屬性進行匹配,而後傳遞給diractive中的scope。至於實現的細節和原理,這裏我就不說了(實際上是不大清楚)。

(3)&

& 方式提供一種途經使directive 能在父 scope 的上下文中執行一個表達式。此表達式能夠是一個 function。其實說白了,就是可使用在父scope中定義的函數。

好比:當你寫了一個 directive,當用戶點擊按鈕時,directive 想要通知 controller,controller 沒法知道 directive 中發生了什麼,也許你能夠經過使用 angular 中的 event 廣播來作到,可是必需要在 controller 中增長一個事件監聽方法。
最好的方法就是讓 directive 能夠經過一個父 scope 中的 function,當 directive 中有什麼動做須要更新到父 scope 中的時候,能夠在父 scope 上下文中執行一段代碼或者一個函數。

 app.controller("ctl1", function ($scope) {
        $scope.value = "hello world";
        $scope.click = function () {
            $scope.value = Math.random();
        };
    }).directive("testDirective", function () {
        return {
            scope: {
                action: "&"
            },
            template: '<input type="button" value="在directive中執行父scope定義的方法" ng-click="action()"/>'
        }
    })
<div  ng-controller="ctl1">
        <div>父scope:
            <div>Say:{{value}}</div>
        </div>
        <div>隔離scope:
            <div isolated-directive action="click()"></div>
        </div>
</div>

在上面的例子中,咱們的屬性action賦值爲一個方法:action="click()",這樣一寫,一眼就看出來是個什麼東西了,好像也沒什麼好解釋的。

 

5.controller、require以及link

 這三個涉及到指令的執行過程,本人暫時尚未比較徹底的理解,因此這裏只能讓你們去看別人寫的博客了(原諒我太笨);

鏈接在頂部。嗯。    ↑點擊返回頂部

相關文章
相關標籤/搜索