[angular] 篇 指令中的scope


scope參數有以下幾種方式:

  1,不填,默認為scope:false

  2,scope:true

  3,scope:{}

  4,

scope:{

    name: '=',

    age: '@',

    say: '&'    

   }

下面我來分別說明他們之間的用法:

  第一種:看代碼

<script>
    angular module('exampleApp', [])
        .controller('scopeCtrl', function ($scope) {
          // do something 
         });
        .directive('scopeDome', function () {
             return {
                 template:
                     "<div class='body'>Name:<input ng-model='name'></div>"
             }
         })
</script>

這里沒有對scope做定義,則angular會調用默認值(scope:false),這時指令中的作用域即是其父級所處的作用域,這里可以調用到父級作用中的變量和方法;

如:

<script type="text/javascript">
        angular.module("exampleApp", [])
            .directive("scopeDemo", function () {
                return {
                    template: function() {
                        return angular.element(
                            document.querySelector("#scopeTemplate")).html();
                    },
                    link: function (scope, element, attrs) {
                        scope.func(); // 調用父級控制器里的方法;
                    }
                }
            })
        .controller("scopeCtrl", function ($scope) {
            $scope.data = { name: "Adam" };
            $scope.city = "London";
            $scope.func = function () {
                alert('you can call me!');
            }
        });
    </script>

  第二種:看代碼

js部分:

<script type="text/ng-template" id="scopeTemplate">
    <div class="panel-body">
        <p>Name: <input ng-model="data.name" /></p>
        <p>City: <input ng-model="city" /></p>
        <p>Country: <input ng-model="country" /></p>
    </div>
</script>
<script type="text/javascript">
    angular.module("exampleApp", [])
        .directive("scopeDemo", function () {
            return {
                    template: function() {
                        return angular.element(
                            document.querySelector("#scopeTemplate")).html();
                    },
                    scope: true,
                    link: function (scope, element, attrs) {
                        scope.func();
                    }
                }
            })
        .controller("scopeCtrl", function ($scope) {
            $scope.data = { name: "Adam" };
            $scope.city = "London";
            $scope.func = function () {
                alert('ok');
            }
        });
</script>

HTML部分

<body ng-controller="scopeCtrl">
    <div class="panel panel-default">
        <div class="panel-body" scope-demo></div>
        <div class="panel-body" scope-demo></div>
    </div>
</body>

在HTML中有兩處調用了這個指令,但生產的效果是不太一樣的,在運行時

效果是,Name是同步的(上下改變任何一個另一個都會跟着變),City和Country卻是獨立的,上下兩個改變都不會影響到另外一個;

原因是scope:true允許我們在同一個控制器中創造一個新作用域,但這個作用域是可以繼承其父級的作用域的屬性和方法的,那么是不是跟沒寫scope一樣了,其實不然,因為他畢竟創造了自己的作用域,那么他的自由性就會比沒寫scope強,那么為什么有的能動態一起變,有的不能呢,那就看看他們的數據屬性吧:

<div class="panel-body">
    <p>Name: <input ng-model="data.name" /></p>
    <p>City: <input ng-model="city" /></p>
    <p>Country: <input ng-model="country" /></p>
</div>
在控制器中:
.controller("scopeCtrl", function ($scope) { $scope.data = { name: "Adam" }; $scope.city = "London"; $scope.func = function () { alert('ok'); } });
名稱 描述
data.name 這個屬性是在一個對象上定義的,意味着這個值將會在指令中的各個實例之間共享,而且所有綁定到該屬性的輸入框元素將會保持同步
city 這個屬性是在控制器的作用域上直接被賦值的,意味着指令所有的作用域將會從同一個初始值開始,但是在輸入框元素被修改時會在自己的作用域上創建和修改自己的版本
country 這個屬性沒有被賦任何值,當相應的輸入框元素被修改時, 指令的每個實例將會創建出獨立的county屬性。

  第三種:看代碼

<script type="text/javascript">
        angular.module("exampleApp", [])
            .directive("scopeDemo", function () {
                return {
                    template: function() {
                        return angular.element(
                            document.querySelector("#scopeTemplate")).html();
                    },
                    scope: {}
                }
            })
        .controller("scopeCtrl", function ($scope) {
            $scope.data = { name: "Adam" }; // 這兩個方法將不能傳到指令中,供指令使用
            $scope.city = "London";
        });
    </script>

scope:{} 表示告訴angular這個指令要創建一個獨立(隔離)的作用域,這樣這個獨立的作用域就不能繼承外界的父級控制器的作用域。這樣的好處是指令在復用時不會污染到外界的父級作用域。

   第四種

第四種是第三種方式的強化,即雖然我的作用域與外界隔離了,但有一些參數(數值,屬性,方法)還是想從外界獲得。那么該如何獲得呢,

angular提供了三種方法供我們使用,分別是 ‘=’、 ‘@’、 ‘&’, 他們的作用分別是:

  @: 通過屬性值進行綁定,但是單向的,即外界控制器可以把值傳進來供內部使用,但內部對這個屬性值進行修改時不會影響到外部的;

  js部分

<script type="text/ng-template" id="scopeTemplate">
        <div class="panel-body">
            <p>Data Value: {{local}}</p>
        </div>
    </script>
    <script type="text/javascript">
        angular.module("exampleApp", [])
            .directive("scopeDemo", function () {
                return {
                    template: function() {
                        return angular.element(
                            document.querySelector("#scopeTemplate")).html();
                    },
                    scope: {
                        local: "@nameprop"
                    }
                }
            })
        .controller("scopeCtrl", function ($scope) {
            $scope.data = { name: "Adam" };
        });
    </script>

HTML部分

<body ng-controller="scopeCtrl">
    <div class="panel panel-default">
        <div class="panel-body">
            Direct Binding: <input ng-model="data.name" /> // 這里改變下面會跟着改變
        </div>
        <div class="panel-body" scope-demo nameprop="{{data.name}}"></div> // 跟着上面數值動態變化
    </div>
</body>

指令中的local通過nameprop獲得外部屬性data.name,所以在控制器中的data.name變化時,指令中的local也會跟着改變;(但如果是只改變local的值,外界的data.name是不會變的);

  =: 通過屬性進行雙向數據綁定,內外變化會保持一致;

js部分

<script type="text/ng-template" id="scopeTemplate">
        <div class="panel-body">
            <p>Data Value: <input ng-model="local" /></p>
        </div>
    </script>
    <script type="text/javascript">
        angular.module("exampleApp", [])
            .directive("scopeDemo", function () {
                return {
                    template: function() {
                        return angular.element(
                            document.querySelector("#scopeTemplate")).html();
                    },
                    scope: {
                        local: "=nameprop"
                    }
                }
            })
        .controller("scopeCtrl", function ($scope) {
            $scope.data = { name: "Adam" };
        });
    </script>

HTML部分

<body ng-controller="scopeCtrl">
    <div class="panel panel-default">
        <div class="panel-body">
            Direct Binding: <input ng-model="data.name" />
        </div>
        <div class="panel-body" scope-demo nameprop="data.name"></div>
    </div>
</body>

顯示的效果:

指令和控制器雙方通過 local: "=nameprop" 進行雙向數據綁定;

  &: 調用父級作用域中的方法(function);

js部分

<script type="text/ng-template" id="scopeTemplate">
        <div class="panel-body">
            <p>Name: {{local}}, City: {{cityFn()}}</p>
        </div>
    </script>
    <script type="text/javascript">
        angular.module("exampleApp", [])
            .directive("scopeDemo", function () {
                return {
                    template: function () {
                        return angular.element(
                            document.querySelector("#scopeTemplate")).html();
                    },
                    scope: {
                        local: "=nameprop",
                        cityFn: "&city"
                    }
                }
            })
        .controller("scopeCtrl", function ($scope) {
            $scope.data = {
                name: "Adam",
                defaultCity: "London"
            };
            $scope.getCity = function (name) {
                return name == "Adam" ? $scope.data.defaultCity : "Unknown";
            }
        });
    </script>

HTML部分

<body ng-controller="scopeCtrl">
    <div class="panel panel-default">
        <div class="panel-body">
            Direct Binding: <input ng-model="data.name" />
        </div>
        <div class="panel-body" scope-demo 
             city="getCity(data.name)" nameprop="data.name"></div>
    </div>
</body>

city特性的值是一個表達式,調用了getCity行為並將data.name屬性作為參數傳入進行處理。要使這個表達式在隔離作用域中可用,在scope中添加 cityFn: "&city",前綴‘&’就告訴angular,我想將所指定特性的值(cityFn)綁定到一個函數,剩下就是在指令中調用這個函數表達式了:{{cityFn()}}

 

PS:這里所有指令作用域跟外界交互都是通過屬性值傳入的:<div class="panel-body" scope-demo city="getCity(data.name)" nameprop="data.name"></div>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM