angulajs 詳解 directive 中 的 scope 概念


   Directive 是 angularjs 中最重要的概念,我的理解就是自定義html tag, 這個自定的tag 瀏覽器不會解析,會有angularjs 來動態解析。

 

   比如在html 中添加 <myPannel title="title" description="pannel description"></mypanel>, 這個myPannel tag 瀏覽器顯然不認識,這個其實就是一個 directive. 這個directive 我們必須在js 代碼中進行定義並且為其設置顯示的html模板,才能讓其正常在頁面中顯示。

   本文將假設你已經知道directive 的概念,並且知道如何創建一個自定義的directive. 對於這部分內容,本文不做介紹,本文主要介紹在自定義directive 中一個非常重要的屬性 scope.

   在angularjs 啟動的時候,會自動創建一個rootScope 對象。 創建controller和directive 的時候,會自動創建自己的私有scope對象,私有scope從rootScope繼承. 

   Directive 中的scope 

 所有的directives 都有自己的 scope 對象。 在默認的情況下,directive  不會創建他們自己的scope. 他們會用他們父對象的scope作為自己的scope.  但是 angularjs 允許改變這種默認行為。

   比如下面的列子:   

var app = angular.module("myAPP",[]);
app.directive("mySpan",function(){
  return {
      restrict: "EA",
      scope: true,
      link: function(scope,elem,attr){
          
      }
  }    
 });

上面的代碼我們創建一個名字為mySpan的directive. 里面有個scope 屬性,我們設置值為 true. 這個屬性,可以設置為下列值中的一個,true, flase 或者{}.

下面我們將接受這三個值得不同。

Directive scope 取值不同的區別

scope : false (Directives 將使用parent 的scope), 這個是默認值

看下面的列子:

1. html 代碼

<div ng-app="myapp">
    
    <div ng-controller="Ctrl1">
        <h2 ng-click="changeName()">Hey {{name}}, Click me to reinit name</h2>
        <div my-directive class='directive'></div>
    </div>
</div>

2.  Js 代碼

var app = angular.module("myapp",[]);

app.controller("Ctrl1",function($scope){
    $scope.name = "Slardar";
    $scope.changeName = function(){
       $scope.name += "_";
    };
});
app.directive("myDirective", function(){
    return {
        restrict: "EA",
        scope: false,
        template: "<div>Your name is : {{name}}</div>"+
        "Change your name : <input type='text' ng-model='name' />"
    };
});

3. css

h2 {
    cursor: pointer;
}
.directive {
    border: 5px solid #F5BF6E;
    padding: 10px;
}

 

預覽地址: http://jsfiddle.net/od3a4ddw/9/

可以看到,在directive 里面的name 屬性和controller 里面的name是一個對象。也就是說directive 使用了其parent 的scope 對象作為自己的scope對象。當在controller 中 改變name 對象的值時,directive 的name 會更新, 反之在directive 中更新name 屬性,controller 里面的name 也會更新。 因為他們其實是一個對象。

 

scope : true(Directives 會創建一個新的scope,但是創建的這個scope 將從parent controller 中的 scope 對象繼承。)

 當設為false的時候,directive 會使用parent 對象的scope 對象, 設為為true 會創建一個scope 對象,但是從parent 的scope 對象繼承。 這兩句話,好像有點不好理解。

我們修改上面的js 代碼,將scope 對象設為true

var app = angular.module("myapp",[]);

app.controller("Ctrl1",function($scope){
    $scope.name = "Slardar";
    $scope.changeName = function(){
        $scope.name +='_';
    };
});
app.directive("myDirective", function(){
    return {
        restrict: "EA",
        scope: true,
        template: "<div>Your name is : {{name}}</div>"+
        "Change your name : <input type='text' ng-model='name' />"
    };
});

預覽地址: http://jsfiddle.net/od3a4ddw/10/

點擊 里面的header, 可以看到在directive 里面的name 和controller 中的name 同時在改變 (也就是說在這個時候,directive 里面name 對象是從parent 對象直接獲取到的(繼承的原因)。但是當我們在directive 里面的textbox 輸入的時候,發現對name 對象的修改不再影響 parentscope 的name 屬性。 這是因為, directive 里面的name 對象是在 text box 里面的 onchange 事件后觸發的創建的。也就是說directive 在text onchange 事件發生后創建了自己的name 對象。 同時在這個時候 再次點擊header 發現directive 里面的name 值不再受到parent scope 中name 的影響。

 

Scope : {}(Directives 會創建一個新的隔離scope,這個隔離的scope 不從parent scope對象繼承)

這個官方推薦的寫scope 的方式, 這樣就避免的directive 中的對象和parent 的對象相互影響,但是由於創建的新的隔離對象是個全新的空對象,因為為這個對象賦值就變成了一個問題。

看下面的列子:

修改js 代碼如下

var app = angular.module("myapp",[]);

app.controller("Ctrl1",function($scope){
    $scope.name = "Slardar";
    $scope.changeName = function(){
        $scope.name += "-";
    };
});
app.directive("myDirective", function(){
    return {
        restrict: "EA",
        scope: {},
        template: "<div>Your name is : {{name}}</div>"+
        "Change your name : <input type='text' ng-model='name' />"
    };
});

 

預覽地址 :http://jsfiddle.net/qggdk7gg/

從上面的列子可以看到,點擊header 文字的時候,direct里面name 始終未空,這是因為directive 里面的scope 是個隔離的scope, 它對parent的scope變量一無所知。

但是我們可以通過下面的方式將值從parent 對象中傳遞到 directive 中。

傳值有以下三種方式:

 通過 @ 傳值  (字符串綁定,one way binding(單向綁定),就是傳遞字符串到directive 進行顯示),在調用directive 的時候,需要對 attribute 使用 {{}} 進行傳值。

 通過  = 傳值   (模型 綁定, two way bingding(雙向綁定)) 在調用directive 的時候,需要對 attribute 使用  模型名稱  進行傳值。

 通過 & 傳值 (方法綁定)

 下面看完整的列子:

1. html 代碼

<div ng-app="app">
    
    <div class="parent" ng-controller="MainCtrl">
        <div class="line">
            Name inside parent scope is: <strong>{{name}}</strong>  
            <input type="button" ng-click="changeName()" value="Change name" />
        </div> 
        <div class="line">
            title in parent scope is: {{title}} 
            <input type="button" ng-click="changeTitle()" value="Change title" />
        </div>
        <div class="directive" my-directive
            name="{{name}}"
            title="title"
            change-name="changeName()"
        ></div>
    </div>
</div>

2. JS 代碼

var app = angular.module("app", []);

app.controller("MainCtrl", function( $scope ){
    $scope.name = "Slardar";
    $scope.title = "Slardar_title";
    $scope.changeName = function(){
     $scope.name += '_';
    };
    $scope.changeTitle = function(){
     $scope.title += '_';
    }
});

app.directive("myDirective", function(){
    
    return {
        restrict: "EA",
        scope: {
            name: "@",
            title: "=",
            changeName: "&"
        },
        template: [
            "<div class='line'>",
            "Title : <strong>{{title}}</strong>;<br/>Name : <strong>{{name}}</strong>;  Change name:<input type='text' ng-model='name' /><br/>",
            "</div><div class='line'>",           
            "<br/><input type='button' ng-click='changeName()' value='Change Name'/>"
        ].join("")    
    };
});

3. Css 

.parent {
    border: 20px solid #676767;
    padding : 20px;
}
.parent,.directive {
    position: relative;
}
.parent:after,.directive:after {
    display: inline;
    color: #fff;
    font-size: normal;
    position: absolute;
    top:-20px;
    left:-20px;
    z-index: 100;
    padding: 1px 5px;
    background-color: rgba(0,0,0,0.5);
}
.parent:after {
    content: "MainCtrl Scope";
}
.directive {
    padding: 20px;
    border: 20px solid #cbccdd;
    margin-top: 20px;
}
.directive:after {
    content: "Directive Scope"
}
.line {
    border-bottom: 1px dotted #ccc;
    padding: 5px 0;
}

完整演示地址: http://jsfiddle.net/g5kdns5x/1/

上面可以 看以看到完整的directive 定義

 <div class="directive" my-directive
            name="{{name}}"
            title="title"
            change-name="changeName()"
        ></div>

 

其中 name 屬性 用 @ 定義  單向字符串綁定,后面使用 {{}}進行賦值。 列子中 只是傳遞name 屬性值在directive 中系那是。

title 用 = 定義 模型綁定, 后面使用 scope 中的屬性名字。  列子中傳遞 title 模型到 directive 中, 在direct 中對title 模型進行修改會同步到parent 對象的title 中。

change-name 用 & 定義,方法綁定。后面直接跟方法調用。 例子中傳遞了changeName 方法到 directive 里面,使的在directive里面可以使用 parent 對象里面定義的changeName 方法。

 

好了,以上就是我對directive 中關於scope 定義的介紹,希望對大家的學習有所幫助。

 


免責聲明!

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



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