编辑:
这个plunker有一个功能性的例子:
http://plnkr.co/edit/GFQGP0q3o9RjLAlRANPS?p=preview
外部范围有$ scope.name ='唐纳德'
所有指令都声明为:
<directive-name binding="name">
这是一个多部分的问题。我试图更好地理解具有监视或绑定到外部范围变量的孤立范围。
使用非隔离范围指令,一切正常:
// [WORKS]
.directive('noScopeWithWatch', function(){
return {
restrict: 'E',
link: function(scope, lElement, attrs) {
scope.$watch(attrs.binding, function(name){
lElement.text('Hello ' + name);
});
}
};
})
// returns Hello Donald
令人困惑的部分是当我试图隔离范围并保持绑定时。所以我要求的是澄清为什么下面的一些例子有效,而有些则没有。
如果我只是用“普通”绑定添加范围隔离,它就会失败:
// 1. [FAILS]
.directive('scopeWithWatch', function(){
return {
restrict: 'E',
link: function(scope, lElement, attrs) {
scope.$watch(attrs.binding, function(name){
lElement.text('Hello ' + name);
});
},
scope: { // new content
binding: '=' // new content
} // new content
};
})
// returns Hello undefined
但是,将watch中的绑定变量用作字符串可以使其工作:
// 2. [WORKS]
.directive('scopeWithWatchString', function(){
return {
restrict: 'E',
link: function(scope, lElement, attrs) {
scope.$watch('binding', function(b){ // new content
lElement.text('Hello ' + b);
});
},
scope: {
binding: '='
}
};
})
// returns Hello Donald
虽然使用绑定变量作为对象失败但是:
// 3. [FAILS]
.directive('scopeWithWatchObject', function(){
return {
restrict: 'E',
link: function(scope, lElement, attrs) {
scope.$watch(binding, function(b){ // new content
lElement.text('Hello ' + b);
});
},
scope: {
binding: '='
}
};
})
// Does not work at all
// Console output - ReferenceError: binding is not defined
尝试在孤立范围内引用绑定变量也不起作用,但至少不会导致异常:
// 4. [FAILS]
.directive('scopeWithWatchScopeObject', function(){
return {
restrict: 'E',
link: function(scope, lElement, attrs) {
scope.$watch(scope.binding, function(b){ // new content
lElement.text('Hello ' + b);
});
},
scope: {
binding: '='
}
};
})
// returns Hello undefined
事实证明,在模板中的胡须中使用绑定变量可以起作用:
// 5. [WORKS]
.directive('scopeWithTemplate', function(){
return {
restrict: 'E',
template: 'Hello {{binding}}', // new content and linker removed
scope: {
binding: '='
}
};
})
// returns Hello Donald
但是尝试将它们用作链接器中的胡须并不会。
// 6. [FAILS]
.directive('scopeWithWatchStringUsingMustashes', function(){
return {
restrict: 'E',
link: function(scope, lElement, attrs) { // new content
scope.$watch('binding', function(){ // new content
lElement.text('Hello {{binding}}'); // new content
}); // new content
}, // new content
scope: {
binding: '='
}
};
})
// returns Hello {{binding}}
以下是摘要:
http://plnkr.co/edit/GFQGP0q3o9RjLAlRANPS?p=preview (我现在的版本是78,如果您想在答案中使用它,请分叉。)
有人可以向我解释为什么有些例子有效,而其他例子没有。
答案 0 :(得分:4)
这有一个简单的答案,适用于此处的所有示例。关于$compile的Angular文档解释了这一点,但很容易误解。隔离范围的整个目的是创建一个仅由声明它的指令消耗的范围。为此,将创建一个新变量,将该值存储为父作用域的别名。
有三种主要定义类型:@
,=
,&
@或@attr - 将本地范围属性绑定到DOM属性的值。结果总是一个字符串,因为DOM属性是字符串。
= or = attr - 在本地范围属性和通过attr属性的值定义的name的父范围属性之间设置双向绑定。
&安培;或&amp; attr - 提供了一种在父作用域的上下文中执行表达式的方法。
@
和=
之间的唯一区别是双向支持。 =
定义仍将返回字符串结果。
所以,按顺序,你拥有的是:
binding='name'
与binding: '='
匹配,'binding'
可作为隔离范围内的别名访问。
'isolate'范围与正常范围的不同之处在于它不是从父范围原型继承的。这在创建可重用组件时非常有用,这些组件不应该意外地读取或修改父范围中的数据。
$compile
自动处理。lElement.text
只是文本。在文本分配中使用表达式需要在将文本发送到dom之前进行额外的手动编译步骤,否则{{}}
表达式将被视为纯文本。
答案 1 :(得分:2)
让我试着解决这些问题
attrs.binding
的值为"name"
,隔离范围内没有name
属性。binding
属性上而起作用。binding
在隔离范围内定义,并且可以正常工作lElement.text('Hello {{binding}}');
,它需要编译要评估的表达式的内容,因此这个表达式不起作用。当你说
时 <scope-with-watch binding="name"></scope-with-watch>
并且执行隔离范围,绑定在父作用域上定义的name
属性和隔离作用域上的binding
属性之间。