В AngularJS, если дочерняя директива не может получить доступ к области действия своего непосредственного родителя, будет ли она наследовать область действия своего ближайшего, не изолированного предка?

У меня есть два примера в пользу вышеупомянутого утверждения -

1) При использовании $ scope ( http://plnkr.co/edit/kFM77mVReS7AUwZsNzCV?p=preview) -

<!DOCTYPE html>
<html>

  <head>
    <script src="//code.angularjs.org/snapshot/angular.min.js"></script>
    <script>
      angular
          .module('myApp', [])
          .directive('directive1', function() {
            return {
              controller: ['$scope', function($scope) {
                $scope.name = 'Directive1';
              }]
            };
          })
          .directive('directive2', function() {
            return {
              controller: ['$scope', function($scope) {
                $scope.name = 'Directive2';
              }],
              scope: {}
            };
          })
          .directive('directive3', function() {
            return {
              template: 'I am {{name}}'
            };
          });
    </script>
  </head>

  <body ng-app='myApp'>
    <directive1>
      <directive2>
        <directive3>
        </directive3>
      </directive2>
    </directive1>
  </body>

</html>

2) При использовании контроллера как ( http://plnkr.co/edit/zmIRa1t87ZIMDS6X5rNo?p=preview)-

 <!DOCTYPE html>
<html>

  <head>
    <script src="//code.angularjs.org/snapshot/angular.min.js"></script>
    <script>
      angular
          .module('myApp', [])
          .directive('directive1', function() {
            return {
              controller: function() {this.name = 'Directive1';},
              controllerAs: 'ctrl1'
            };
          })
          .directive('directive2', function() {
            return {
              controller: function() {this.name = 'Directive2';},
              controllerAs: 'ctrl2',
              transclude: true,
              template: '<ng-transclude></ng-transclude>',
              scope: {}
            };
          })
          .directive('directive3', function() {
            return {
              template: 'I am {{ctrl1.name}}'
            };
          });
    </script>
  </head>

  <body ng-app='myApp'>
    <directive1>
      <directive2>
        <directive3>
        </directive3>
      </directive2>
    </directive1>
  </body>

</html>

Вывод обоих кодов - я директива1, которая показывает, что директива 3 наследует область действия директивы 1(она не будет обращаться к области действия директивы 2, поскольку она имеет изолированную область видимости), что доказало, что я ошибался, предполагая, что изолированная область действия нарушит цепочка наследования между его родительской директивой и ее дочерними директивами и, следовательно, ни одна из ее дочерних директив не сможет получить доступ к области действия любой из своих директив-предков.

Я что-то здесь упускаю или моя концепция наследования области действия совершенно неверна?

2 ответа

Решение

Вывод <...> доказал, что я не прав, предполагая, что изолированная область действия разорвет цепочку наследования между его родительской директивой и дочерними директивами.

Само доказательство неверно. Это поведение характерно для директив без шаблонов и похоже на включение. В коде выше directive1 не имеет собственной сферы применения и $scope.name = 'Directive1' установлен в корневой области видимости. И оба directive1 а также directive2 скомпилированы с корневой областью, потому что у них нет шаблонов и нет собственных областей.

Указанное предположение будет правильным, если директивы имеют свои собственные шаблоны, например:

  .directive('directive2', function() {
    return {
      template: '<directive3>'
      controller: ['$scope', function($scope) {
        $scope.name = 'Directive2';
      }],
      scope: {}
    };
  })

Использование scope:true во всех ваших 3 директивах, и он сможет получить доступ ко всем возможностям родителей

Примечание: scope:true будет наследовать свойства от родителя, но scope:{} не будет наследовать свойства от родителя.

<!DOCTYPE html>
<html>

<head>
  <script src="//code.angularjs.org/snapshot/angular.min.js"></script>
  <script>
    angular
      .module('myApp', [])
      .directive('directive1', function() {
        return {
          controller: ['$scope', function($scope) {
            $scope.name = 'Directive1';
          }],
          scope: true
        };
      })
      .directive('directive2', function() {
        return {
          controller: ['$scope', function($scope) {
            $scope.name = 'Directive2';
          }],
          scope: true
        };
      })
      .directive('directive3', function() {
        return {
          template: 'I am {{name}}',
          scope: true
        };
      });
  </script>
</head>

<body ng-app='myApp'>
  <directive1>
    <directive2>
      <directive3></directive3>
    </directive2>
  </directive1>
  
  <br>
  
  <directive1>
    <directive3></directive3>
  </directive1>

  <br>

  <directive2>
    <directive3></directive3>
  </directive2>

</body>

</html>

Другие вопросы по тегам