简体   繁体   中英

how does angular deal with elements with multiple directives

如果一个元素有多个指令,一个带有scope:false ,一个带有scope:true ,一个带有scope:{}指令,angular如何处理这个元素?

If you include all three directives asking for all three scope options on the same element, you get an error. true and false are compatible and use the same scope, but adding {} causes:

Error: [$compile:multidir] Multiple directives [isolatedScope, trueScope]
asking for new/isolated scope on:
<div false-scope="" true-scope="" isolated-scope="">

In this case, true and {} conflict when true tries to create a new, inheriting scope and {} tries to create a new, isolated scope, which is reasonable and perhaps expected. The $compile docs say:

If multiple directives on the same element request a new scope, only one new scope is created.

If you have multiple directives with scope: true , they're fine and you get just one, but scope: {} asks for a different kind, and Angular can't produce both. Directives can be declared with priority , so they could have quietly picked a winner, but that would lead to all sorts of surprises, so they wisely decided to shout about it.


Here's a Plunker demonstrating it. I put all three scopes on a single div , then declared data in each of them using data available in the parent scope. If you comment out the scope: {} , it works fine and you can see the false and true scopes sharing. I haven't investigated whether false or true won out, but I suspect true because it indicates to $compile that a new scope is wanted.

HTML:

<body ng-controller="MainCtrl">
  <div false-scope true-scope isolated-scope>
    <b>False directive</b>
    <ul>
      <li>Loaded: {{ falseDirectiveLoaded }}</li>
      <li>Data: {{ falseDirectiveData }}</li>
    </ul>
    <b>True directive</b>
    <ul>
      <li>Loaded: {{ trueDirectiveLoaded }}</li>
      <li>Data: {{ trueDirectiveData }}</li>
    </ul>
    <b>Isolated directive</b>
    <ul>
      <li>Loaded: {{ isolatedDirectiveLoaded }}</li>
      <li>Data: {{ isolatedDirectiveData }}</li>
    </ul>
  </div>
</body>

JS:

app.controller('MainCtrl', function($scope) {
  $scope.one = 1;
  $scope.two = 2;
  $scope.three = 3;
});

app.directive('falseScope', function() {
  return {
    restrict: 'A',
    scope: false,
    link: function(scope, element) {
      scope.falseDirectiveLoaded = true;
      scope.falseDirectiveData = [scope.one, scope.two, scope.three];
    }
  }
});

app.directive('trueScope', function() {
  return {
    restrict: 'A',
    scope: true,
    link: function(scope, element) {
      scope.trueDirectiveLoaded = true;
      scope.trueDirectiveData = [scope.one, scope.two, scope.three];
    }
  }
});

app.directive('isolatedScope', function() {
  return {
    restrict: 'A',
    scope: {},
    link: function(scope, element) {
      scope.isolatedDirectiveLoaded = true;
      scope.isolatedDirectiveData = [scope.one, scope.two, scope.three];
    }
  }
});

As JS uses duck typing , scope can receive any kind of values though they may filter what angular accepts.

With that in mind, when angular receives the scope, I guess it verifies the type of the argument , and threat it accordly.

  • boolean: let you control if the scope will be inherited
  • object*: let you add "new proprieties" that are bound to that directive
  • others: I don't know how angular behaves if any other type, as a string, is passed

*I guess it only accepts JSON

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM