我一直在使用隔离范围指令一段时间,并且想到了一个问题,看着它的行为:
为什么我不能将我在指令继承范围内定义的变量直接绑定到视图?
让我举一个关于此代码笔的示例: http://codepen.io/anon/pen/VLKjrv
当我在指令控制器中创建一个新的$ scope变量并尝试将其绑定在视图上时,它不起作用。 另一方面,当我将该变量绑定到来自模板指令属性的html时,它确实有效。
查看代码:
<body ng-app="isolated-test-app">
<section ng-controller="isolatedTestCtrl">
<article>
<h1>test1</h1>
<div isolated-directive binding-from-attr="test">
<span ng-bind="test"></span>
<span ng-bind="test2"></span>
</div>
<h1>test2</h1>
<div isolated-directive-number-two binding-from-attr="test">
</div>
</article>
</section>
angular.module('isolated-test-app', [])
.controller('isolatedTestCtrl', function isolatedTestCtrl($scope){
$scope.test = 'Binded from parent controller';
})
.directive('isolatedDirective', function isolatedDirective(){
var directive = {
scope: {
bindingFromAttr: '=',
},
controller: function directiveController($scope){
$scope.test2 = 'Binded from directive controller!';
},
};
return directive;
})
.directive('isolatedDirectiveNumberTwo', function isolatedDirective2(){
var directive = {
scope: {
bindingFromAttr: '=',
},
template:'<span ng-bind="bindingFromAttr"></span>\
<span ng-bind="test2"></span>',
controller: function directiveController($scope){
$scope.test2 = 'Binded from directive controller!';
},
};
return directive;
})
TEST1
从父控制器挂载
TEST2
从父控制器挂载
来自指令控制器!
我期待test1上test2的结果。
为什么会这样?
答案 0 :(得分:6)
指令模板与指令的元素内容在适用范围方面存在差异。
在隔离范围(scope: {}
)指令中,隔离范围适用于模板,但不适用于内容。内容与指令的父级具有相同的范围。另请注意,如果定义了模板,则内容将被模板替换。要使用模板之外的内容,需要“转录”(transclude: true
)(但这不属于此答案的范围)。
如果您感到困惑,可以随时查看$scope.$id
以查看适用的范围:
<div>parent scope: {{$id}} (will be 2)</div>
<isolate-scope>
contents of isolate scope directive: {{$id}} (will also be 2)
</isolate-scope>
<isolate-scope-with-template>
contents will be replaced with the template
</isolate-scope-with-template>
.directive("isolateScopeWithTemplate", function(){
return {
scope: {},
template: "template: {{$id}} (will NOT be 2)"
}
})
(当然,实际$id
可能不同)
在子范围(scope: true
)指令中,适用于内容的范围实际上与应用于模板的范围相同(此处相同 - 模板将替换内容如果它存在,除非你转录)。
现在,回答您的问题:
第一个<span ng-bind="test2"></span>
绑定到父作用域中不存在的$scope.test2
,因此它是空的。
但<span ng-bind="test2"></span>
模板中的isolatedDirectiveNumberTwo
绑定到该指令的隔离范围,该指令定义$scope.test2 = 'Binded from directive controller!'
。
答案 1 :(得分:0)
这是我对http://codepen.io/anon/pen/MwjjBw
中的实验的猜测因此对于测试1,指令范围没有test / test2,因为dom对象属于控制器。因此,为了更新它,你必须使用
$scope.$parent.test2 = "" ;
并且对于测试2,因为模板是作为指令的一部分创建的,因此dom对象属于指令并且也可以由控制器访问(我猜$ compile将其添加到控制器范围/监视中)。
您还可以看到test1没有任何观察者,因为没有绑定发生。
答案 2 :(得分:0)
现在我全面了解,正如New Dev的回答在他的回答中所述
在隔离范围(范围:{})指令中,隔离范围适用于模板,但不适用于内容。内容与指令的父级具有相同的范围。
所以我了解到指令内容和模板之间存在差异,以及如何在隔离的作用域上继承作用域。 对于我的应用程序,将范围设置为true完全解决了我的问题。
此外,kwan245的解决方案是解决这个问题的真正好办法。
这两个答案都清除了我的想法,非常感谢New Dev和kwan245:)