1. 程式人生 > >angularjs 指令詳解

angularjs 指令詳解

del 構造函數 單向 例如 正常 可選參數 詳解 href gif

一、指令定義

對於指令,可以把它簡單的理解成在特定DOM元素上運行的函數,指令可以擴展這個元素的功能。

首先來看個完整的參數示例再來詳細的介紹各個參數的作用及用法:

<div my-directive></div> 
angular.module(‘myApp‘, []) 
.directive(‘myDirective‘, 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 or function(scope, element, attrs, transclude, otherInjectables) { ... }, controllerAs: String, require: String, link:
function(scope, iElement, iAttrs) { ... }, compile: // 返回一個對象或連接函數,如下所示: function(tElement, tAttrs, transclude) { return { pre: function(scope, iElement, iAttrs, controller) { ... }, post: function(scope, iElement, iAttrs, controller) { ... } }
return function postLink(...) { ... } } }; });

二、指令參數的作用和意義(這個地方只選常用的幾種來講一下)

restrict[string]

restrict是一個可選的參數。用於指定該指令在DOM中以何種形式被聲明。默認值是A,即以屬性的形式來進行聲明。
可選值如下:
E(元素)

<my-directive></my-directive> 
A(屬性,默認值)

<div my-directive></div> 
C(類名)

<div class="my-directive:expression;"></div> 
M(註釋)

<--directive:my-directive expression-->

一般考慮到瀏覽器的兼容性,強烈建議使用默認的屬性就可以即即以屬性的形式來進行聲明。最後一種方式建議在不要求逼格指數的時候千萬不要用。

replace[bool]

replace是一個可選參數,如果設置了這個參數,值必須為true,因為默認值為false。默認值意味著模板會被當作子元素插入到調用此指令的元素內部,
例如上面的示例默認值情況下,生成的html代碼如下:

<my-directive value="http://www.baidu.com" text="百度"><a href="http://www.baidu.com">百度</a></my-directive>

如果設置replace=true

<a href="http://www.baidu.com" value="http://www.baidu.com" text="百度">百度</a>

templateUrl[string or function]

templateUrl是可選的參數,可以是以下類型:

  • 一個代表外部HTML文件路徑的字符串;
  • 一個可以接受兩個參數的函數,參數為tElement和tAttrs,並返回一個外部HTML文件路徑的字符串。

無論哪種方式,模板的URL都將通過ng內置的安全層,特別是$getTrustedResourceUrl,這樣可以保護模板不會被不信任的源加載。 默認情況下,調用指令時會在後臺通過Ajax來請求HTML模板文件。加載大量的模板將嚴重拖慢一個客戶端應用的速度。為了避免延遲,可以在部署應用之前對HTML模板進行緩存。

    angular.module(‘app‘,[])
    .directive(‘myDirective‘, function () {
            return { 
                restrict: ‘A‘, 
                templateUrl: function (elem, attr) {
                    return attr.value + ".html";  //當然這裏我們可以直接指定路徑,同時在模板中可以包含表達式
                }
        };
    })

controller[string or function]

controller參數可以是一個字符串或一個函數。當設置為字符串時,會以字符串的值為名字,來查找註冊在應用中的控制器的構造函數.

angular.module(‘myApp‘, []) 
.directive(‘myDirective‘, function() { 
restrict: ‘A‘,  
replace: true,
templateUrl: ‘test.html‘, controller:
‘SomeController‘ })

可以在指令內部通過匿名構造函數的方式來定義一個內聯的控制器

angular.module(‘myApp‘,[]) 
.directive(‘myDirective‘, function() { 
restrict: ‘A‘, 
controller: 
function($scope, $element, $attrs, $transclude) { 
// 控制器邏輯放在這裏
} 
});

我們可以將任意可以被註入的ng服務註入到控制器中,便可以在指令中使用它了。控制器中也有一些特殊的服務可以被註入到指令當中。這些服務有:

1. $scope

與指令元素相關聯的當前作用域。
2. $element
當前指令對應的元素。
3. $attrs
由當前元素的屬性組成的對象。

<div id="aDiv"class="box"></div>
具有如下的屬性對象:
{ 
id: "aDiv", 
class: "box" 
}

三、指令作用域

scope參數[bool or object]

scope參數是可選的,可以被設置為true或一個對象。默認值是false。

html代碼

 <div ng-controller=‘MainController‘ ng-init="myProperty=‘Hello World!‘">
        外部: {{ myProperty}}
        <input ng-model="myProperty" />
        <div my-directive></div>
    </div>

js代碼

    angular.module(‘myApp‘, [])
        .controller(‘MainController‘, function ($scope) {
        })
        .directive(‘myDirective‘, function () {
            return {
                restrict: ‘A‘,
                scope:false,//切換為{},true測試
                priority: 100,
                template: ‘<div>內部:{{ myProperty }}<input ng-model="myProperty"/></div>‘
            };
        });

當我們改變scope的值我們會發現

false:繼承但不隔離技術分享圖片

1.當我們將scope設置為false的時候,我們創建的指令和父作用域(其實是同一個作用域)共享同一個model模型,所以在指令中修改模型數據,它會反映到父作用域的模型中。

true:繼承並隔離技術分享圖片

2.當我們將scope設置為true的時候,我們就新創建了一個作用域,只不過這個作用域是繼承了我們的父作用域;

我覺得可以這樣理解,我們新創建的作用域是一個新的作用域,只不過在初始化的時候,用了父作用域的屬性和方法去填充我們這個新的作用域。它和父作用域不是同一個作用域。

{}:隔離且不繼承 技術分享圖片

3.當我們將scope設置為{}時,意味著我們創建的一個新的與父作用域隔離的新的作用域,這使我們在不知道外部環境的情況下,就可以正常工作,不依賴外部環境。

四、綁定策略

在使用獨立作用域scope的時候,一般有三種綁定傳遞策略, @單向傳遞字符串 =雙向傳遞 &單向傳遞父級的方法

<inputtype="text"ng-model="myUrl">
<div my-directive my-url="{{myUrl}}" my-age="age" change-my-age="changeAge()></div>
angular.module(‘myApp‘,[])
.directive(‘myDirective‘,function(){
return{
restrict:‘A‘,//屬性方式
replace:true,
scope:{
myUrl:‘@‘,//@綁定策略(默認綁定到 my-url指令屬性)
myAge:‘=‘//=雙向綁定(父子互相影響)
changeMyAge:‘&‘ //傳遞父作用域的方法
}, template:‘<a href="{{myUrl}}" ng-click=changeMyAge()>{{ myAge }}</a>‘ } });
  • 在上面的代碼中,我創建了一個指令myDirective 該指令創建了兩個變量 myUrl、myLinkText,並且這倆個變量都是采用@綁定策略

  • 說一下,不管是@=還是&綁定策略,它們都有一個默認的方式,以@綁定策略為例,如上面代碼那麽樣:myUrl:‘@‘,直接用一個@表示綁定的方式,它就會默認得將指令屬性my-url的值賦值給myUrl變量

  • 當然,你不想使用默認的方式,也就是說,你不想myUrl變量綁定my-url的值,而想要綁定其它屬性名的值,那麽你可以在@後加上你希望的屬性名(格式要求:駝峰式)。

  • 如,我想講myUrl綁定到<myDirective></myDirective>指令的some-attr屬性的值,那麽你可以這樣寫:myUrl:‘@someAttr‘

  • 那麽我們知道了指令的myUrl變量的值是如何來的,那麽我們要如何在template中使用它呢?

  • 這個很簡單,看上面的代碼就能很明白了,我們在template中的代碼中需要用表達式的方式對其引用{{myUrl}},這樣我們就能夠使用到myUrl變量的值了~

  1. 本地作用域屬性:使用@符號將本地作用域同DOM屬性的值進行綁定,使指令內部作用域可以使用外部作用域的變量:

  @ 可以在指令中使用綁定的字符串了。

  2. 雙向綁定:通過=可以將本地作用域上的屬性同父級作用域上的屬性進行雙向的數據綁定。就像普通的數據綁定一樣,本地屬性會反映出父數據模型中所發生的改變。
  

  3. 父級作用域綁定 通過&符號可以對父級作用域進行綁定,以便在其中運行函數。意味著對這個值進行設置時會生成一個指向父級作用域的包裝函數。
  要使調用帶有一個參數的父方法,我們需要傳遞一個對象,這個對象的鍵是參數的名稱,值是要傳遞給參數的內容。

angularjs 指令詳解