AngularJS Directive 隔離 Scope 資料互動

weixin_30924079發表於2020-04-04
---------------------------------------------------------------------------------
AngularJS Directive 隔離 Scope 資料互動

什麼是隔離 Scope

AngularJS 的 directive 預設能共享父 scope 中定義的屬性,例如在模版中直接使用父 scope 中的物件和屬性。通常使用這種直接共享的方式可以實現一些簡單的 directive 功能。當你需要建立一個可重複使用的 directive,只是偶爾需要訪問或者修改父 scope 的資料,就需要使用隔離 scope。當使用隔離 scope 的時候,directive 會建立一個沒有依賴父 scope 的 scope,並提供一些訪問父 scope 的方式。

為什麼使用隔離 Scope

當你想要寫一個可重複使用的 directive,不能再依賴父 scope,這時候就需要使用隔離 scope 代替。共享 scope 可以直接共享父 scope,而隔離 scope 無法共享父scope。下圖解釋共享 scope 和隔離 scope 的區別:
圖片

示例可看:

共享 scope

使用共享 scope 的時候,可以直接從父 scope 中共享屬性。因此下面示例可以將那麼屬性的值輸出出來。使用的是父 scope 中定義的值。

js程式碼:

app.controller("myController", function ($scope) {
    $scope.name = "hello world";
    }).directive("shareDirective", function () {
    return {
            template: 'Say:{{name}}'
    }
});

html程式碼

<div ng-controller="myController">
<div share-directive=""></div>
</div>

輸出結果:

Say:hello world

隔離 scope

使用隔離 scope 的時候,無法從父 scope 中共享屬性。因此下面示例無法輸出父 scope 中定義的 name 屬性值。

js程式碼:

app.controller("myController", function ($scope) {
    $scope.name = "hello world";
}).directive("isolatedDirective", function () {
        return {
            scope: {},
            template: 'Say:{{name}}'
        }
});

html程式碼:

<div ng-controller="myController">
<div isolated-directive=""></div>
</div>

輸出結果:

Say:

示例請點選:http://kin-sample.coding.io/angular/directive/share-and-isolated-scope.html

從上圖可以看出共享 scope 允許從父 scope 滲入到 directive 中,而隔離 scope 不能,在隔離 scope 下,給 directive 創造了一堵牆,使得父 scope 無法滲入到 directive 中。

具體文件可以參考:https://docs.angularjs.org/guide/directive#isolating-the-scope-of-a-directive

如何在 directive 中建立隔離 scope

在 Directive 中建立隔離 scope 很簡單,只需要定義一個 scope 屬性即可,這樣,這個 directive 的 scope 將會建立一個新的 scope,如果多個 directive 定義在同一個元素上,只會建立一個新的 scope。

angular.module('app').controller("myController", function ($scope) {
    $scope.user = {
            id:1,
            name:"hello world"
    };
}).directive('isolatedScope', function () {
    return {
        scope: {},
        template: 'Name: {{user.name}} Street: {{user.addr}}'
    };
});

現在 scope 是隔離的,user 物件將無法從父 scope 中訪問,因此,在 directive 渲染的時候 user 物件的佔位將不會輸出內容。

隔離 scope 和父 scope 如何互動

directive 在使用隔離 scope 的時候,提供了三種方法同隔離之外的地方互動。這三種分別是

  • @ 繫結一個區域性 scope 屬性到當前 dom 節點的屬性值。結果總是一個字串,因為 dom 屬性是字串。
  • & 提供一種方式執行一個表示式在父 scope 的上下文中。如果沒有指定 attr 名稱,則屬性名稱為相同的本地名稱。
  • = 通過 directive 的 attr 屬性的值在區域性 scope 的屬性和父 scope 屬性名之間建立雙向繫結。

@ 區域性 scope 屬性

@ 方式區域性屬性用來訪問 directive 外部環境定義的字串值,主要是通過 directive 所在的標籤屬性繫結外部字串值。這種繫結是單向的,即父 scope 的繫結變化,directive 中的 scope 的屬性會同步變化,而隔離 scope 中的繫結變化,父 scope 是不知道的。

如下示例:directive 宣告未隔離 scope 型別,並且使用@繫結 name 屬性,在 directive 中使用 name 屬性繫結父 scope 中的屬性。當改變父 scope 中屬性的值的時候,directive 會同步更新值,當改變 directive 的 scope 的屬性值時,父 scope 無法同步更新值。

js 程式碼:

 app.controller("myController", function ($scope) {
        $scope.name = "hello world";
    }).directive("isolatedDirective", function () {
        return {
            scope: {
                name: "@"
            },
            template: 'Say:{{name}} <br>改變隔離scope的name:<input type="buttom" value="" ng-model="name" class="ng-pristine ng-valid">'
        }
})

html 程式碼:

<div ng-controller="myController">
   <div class="result">
       <div>父scope:
           <div>Say:{{name}}<br>改變父scope的name:<input type="text" value="" ng-model="name"/></div>
       </div>
       <div>隔離scope:
           <div isolated-directive name="{{name}}"></div>
       </div>
        <div>隔離scope(不使用{{name}}):
             <div isolated-directive name="name"></div>
         </div>
   </div>

具體演示請看:http://kin-sample.coding.io/angular/directive/isolated-scope-at-interact.html

= 區域性 scope 屬性

= 通過 directive 的 attr 屬性的值在區域性 scope 的屬性和父 scope 屬性名之間建立雙向繫結。
意思是,當你想要一個雙向繫結的屬性的時候,你可以使用=來引入外部屬性。無論是改變父 scope 還是隔離 scope 裡的屬性,父 scope 和隔離 scope 都會同時更新屬性值,因為它們是雙向繫結的關係。

示例程式碼:

js 程式碼:

 app.controller("myController", function ($scope) {
        $scope.user = {
            name: 'hello',
            id: 1
        };
    }).directive("isolatedDirective", function () {
        return {
            scope: {
                user: "="
            },
            template: 'Say:{{user.name}} <br>改變隔離scope的name:<input type="buttom" value="" ng-model="user.name"/>'
        }
    })

html 程式碼:

<div ng-controller="myController">
    <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>

具體演示請看:http://kin-sample.coding.io/angular/directive/isolated-scope-eq-interact.html

& 區域性 scope 屬性

& 方式提供一種途經是 directive 能在父 scope 的上下文中執行一個表示式。此表示式可以是一個 function。
比如當你寫了一個 directive,當使用者點選按鈕時,directive 想要通知 controller,controller 無法知道 directive 中發生了什麼,也許你可以通過使用 angular 中的 event 廣播來做到,但是必須要在 controller 中增加一個事件監聽方法。
最好的方法就是讓 directive 可以通過一個父 scope 中的 function,當 directive 中有什麼動作需要更新到父 scope 中的時候,可以在父 scope 上下文中執行一段程式碼或者一個函式。

如下示例在 directive 中執行父 scope 的 function。

js程式碼:

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

html 程式碼:

 <div  ng-controller="myController">
        <div>父scope:
            <div>Say:{{value}}</div>
        </div>
        <div>隔離scope:
            <div isolated-directive action="click()"></div>
        </div>
</div>

具體演示請看:http://kin-sample.coding.io/angular/directive/isolated-scope-ad-interact.html

使用小結

在瞭解 directive 的隔離 scope 跟外部環境互動的三種方式之後,寫一些通用性的元件更加便捷和順手。不再擔心在 directive 中改變外部環境中的值,或者執行函式的重重困境了。
更多請參考API文件:https://docs.angularjs.org/api/ng/service/$compile 。
如有紕漏,請指正!

轉載於:https://www.cnblogs.com/oxspirt/p/9229379.html

相關文章