Nemesv 上面提到你应该使用$parent
,但是虽然工作,但这是not正确的解决方案。该解决方案的问题是:
- 它在范围之间创建了高度耦合
ng-if
和控制器范围。
- 因为1、改变
ng-if
to ng-show
会破坏你的代码。
- 一旦你要嵌套更多范围,它就会变得一团糟(
$parent.$parent.$parent....
)
解决方案:
快速正确的解决方案是不定义showIt
直接在您的范围上,而是将其放置在一个对象中(例如component.isVisible
).
解释:
要理解为什么这个看似违反直觉的解决方案有效并且确实是正确的解决方案,您首先需要更多地了解继承如何与 Angular 一起工作:
作用域使用原型继承相互继承,这是 Javascript 中内置的继承形式。这看起来如下:
var myScope = {
showIt : false
}
var ngIfScope = {};
nfIfScope.__proto__ = myScope;
当你现在get的财产ngIfScope
如果对象不存在,它将在其原型中查找以找到它。所以如果你要求ngIfScope.showIt
浏览器会执行以下操作:
if (ngIfScope.hasOwnProperty("showIt")) {
return ngIfScope.getOwnProperty("showIt"); // getOwnProperty does not actually exist in javascript
} else {
return ngIfScope.__proto__.showIt;
}
(实际上,这是递归发生的,但这对于这个例子来说并不重要)。
Setting不过,属性更简单:
ngIfScope.setOwnProperty("showIt", newValue);
现在我们有了这些信息,我们可以看到您最初的实现到底出了什么问题。
我们从以下范围开始:
var myScope = {
showIt : false
}
var ngIfScope = {};
ngIfScope.__proto__ = myScope;
当用户单击显示按钮时,将执行以下代码:
ngIfScope.showIt = true;
结果范围是:
var myScope = {
showIt : false
}
var ngIfScope = {
showIt : true
}
ngIfScope.__proto__ = myScope;
正如你所看到的,新值被写入ngIfScope
,而不是在myScope
正如您可能预期的那样。结果是ngIfScope.showIt
掩盖了来自的变量myScope
and myScope.showIt
实际上根本没有改变。
现在让我们看看如果我们将可见性触发器放置在对象中会发生什么。
我们从新的范围开始:
var myScope = {
component : {
isVisible : false
}
};
var nfIfScope = {};
ngIfScope.__proto__ = myScope;
到目前为止没有太大变化。但现在让我们看看当用户单击按钮时会发生什么:
ngIfScope.component.isVisible = true;
通过一些辅助变量,我们可以看到它是如何在浏览器中执行的:
var tempObject = ngIfScope.component;
tempObject.isVisible = true;
这里的第一行是get手术。自从component
没有定义于ngIfScope
Javascript 引擎将查看原型ngIfScope
(myScope
)在那里找到它,正如我上面所解释的。因此:
tempObject === ngIfScope.__proto__.component === myScope.component
我们现在直接更改值myScope.component
,因此这次变量并没有被掩盖。结果范围是:
var myScope = {
component : {
isVisible : true
}
};
var ngIfScope = {};
var ngIfScope.__proto__ = myScope;
我们现在有了一个工作实现,无需显式绑定到$parent
范围,因此范围之间没有(或很少)耦合。原型继承为我们完成了这项工作,嵌套作用域也可以开箱即用。