iT邦幫忙

DAY 16
1

我在前端 ng 時系列 第 16

初談 directive - scope

本來要繼續上一篇初談 directive 教學。
可是 scope 實在太重要了,決定要多送 scope 幾篇來講解它。

directive scope 屬性說難不是很難,說簡單也不簡單。
不知道的情況下去使用,好像可以 work 就算了。
寫了幾個下來,不覺得 directive 哪裡特別,說好的重複點在哪裡??
( 上面是我一開始學的心情...orz)

就像我 AngularJS 心路歷程寫的,知道 scope 對寫 AngularJS 很有幫助。


scope: false (default)

當 scope 屬性沒有定義的時候,默許值是 false 。
意思就是不會產生新的 scope,該 directive 操作的 scope 跟所屬的 controller 是同一個。

不會產生新 scope 問題是,所有相同的 directive 都分享同一個值。
所以不能做出重複利用並且顯示不同值的 directive。

範例:http://plnkr.co/edit/0hzvtQgWEpWEKfeFluYP

myDirective 裡的 ng-model 綁定的 myName 都是分享 myCtrl 的 myName。
所以範例裡更新其中一個 input,另外一個也會一起被更新。

<body ng-app="myExample" ng-controller="myCtrl”>
  <!-- share same value from myCtrl -->
  <div my-directive></div>
  <div my-directive></div>


angular.module('myExample', [])
  .controller('myCtrl', ['$scope', function($scope) {
    // 跟 directive 的 myName 是同一個
    $scope.myName = 'luffy';
  }]).directive('myDirective', function() {
    return {
      template: '<input type="text" ng-model="myName"/>'
    };
  });

scope: true

產生一個新的 children scope 並且繼承 parent scope。
修改上一個範例,把 myDirective 設定 scope: ture。
會變得因產生 children scope 關係,所以兩個 myDirective 會去新增自己的 {{myName}}。

可是這裡假如 myCtrl 的裡頭讓 children scope 繼承的值是 object 會發生什麼事呢?
範例:http://plnkr.co/edit/veQsg9EU7HfxLGJkebiy

angular.module('myExample', [])
  .controller('myCtrl', ['$scope', function($scope) {
    $scope.myName = 'luffy';
    $scope.myObj = {
      title: 'onepiece'
    };
  }]).directive('myDirective', function() {
    return {
      scope: true,
      template:
          '<div>' +
            '名稱:<input type="text" ng-model="myName"/>' +
            '抬頭:<input type="text" ng-model="myObj.title" />' +
          '</div>'
    };
  });

會發現不管更新哪一個 “抬頭” input ,都會影響到 myCtrl scope 裡的 myObj.title。
可是更新 “名稱” input 卻不會影響到 myCtrl,因為 “名稱” input 綁的是 String (primary type)

( It’s how scope inheritance work... 這裡就不解釋了,請直接看教學)

假如需求是 myDirective 是產生自已的 myObj,而不想改到 parent,就會有問題了。

可是假如說,搞不好我們就是想要讓 myDirective 修改 parent 的 myObj.title,那 scope: true 還會有什麼問題呢?
parent scope 現在就是對 children scope 採取開放狀態。
所以假如有另外一個 direcitve 在 link function 不小心動到不該修改的,我們就會發生問題了...

app.directive('myDirective', function() {
    return {
      scope: true,
      link: function (scope) {
          // override myCtrl.myObj !
           scope.myObj = {};
          // 或是不小心打錯字, 沒有更新到 parent.myObj.title
          scope.myObj.titll = ‘hello’;
      }
  }); 

總結一下,
雖然用繼承的方式 (scope: true) 設定 directive scope 很方便,
可是長久下來畫面上的 scope 的關係會變得很複雜,非常不好維護。

接下來進入下一篇的主題,isolate scope。


參考書籍: Pro AngularJS

作者: Adam Freeman 出版社: Apress


上一篇
初談 directive
下一篇
初談 directive - isolate scope
系列文
我在前端 ng 時30

2 則留言

0
lai32290
iT邦新手 5 級 ‧ 2016-02-25 02:53:32

超級棒的!!!

0
biggy2003211
iT邦新手 5 級 ‧ 2018-08-05 12:34:34

謝謝你這系列的文章,
最近剛好遇到 JQuery UI Plugin 要整合至 Directive 的需求,
學習了。

我要留言

立即登入留言