В 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>