我注意到Angular在阅读$ scope属性方面不够保守。当app / controller首次实例化时,通过$ scope公开的模型中定义的每个绑定属性都会被读取两次。当任何属性更改时,将再次读取所有绑定属性。
有人可以解释为什么(或者我做错了什么)?
这里有一些代码可供说明。
我在一个对象上定义了两个属性,这样我就可以在任何时候读取该属性console.log
。
var obj = [];
Object.defineProperty(obj, "a", {
get: function(){
console.log("get obj.a: " + this.aVal);
return this.aVal;
},
set: function(val){
this.aVal = val;
console.log("set obj.a = " + this.aVal);
}
});
Object.defineProperty(obj, "b", {
get: function(){
console.log("get obj.b: " + this.bVal);
return this.bVal;
},
set: function(val){
this.bVal = val;
console.log("set obj.b = " + this.bVal);
}
});
var app = angular.module("App", [])
.controller("TestCtrl", function($scope){
$scope.foo = obj;
});
<div ng-app="App">
<div ng-controller="TestCtrl">
<input type="text" ng-model="foo.a"></input>
<input type="text" ng-model="foo.b"></input>
</div>
</div>
控制台日志如下:
首次运行应用程序时,两个属性都被调用两次:
get obj.a: undefined
get obj.b: undefined
get obj.a: undefined
get obj.b: undefined
为obj.a输入“x”时,将再次读取这两个属性
set obj.a = x
get obj.a: x
get obj.b: undefined
答案 0 :(得分:1)
Angular处理双向绑定。它的方式是通过脏检查。它会检查摘要顶部的任何监视属性,然后检查摘要的底部(两次)。然后比较这些值以查看是否有任何变化。这是它知道是否需要重新绑定UI的方式。请阅读this article以供参考。
摘要周期在范围内调用$apply
的任何时候运行。 Angular经常这样做(在它自己的指令中,例如ng-click
)。
答案 1 :(得分:0)
尝试使用firebug捕获堆栈,但它似乎(我知道它的角度)来自$ watch实现 - 它必须首先评估对象的当前散列以启动&#34; listen&#34;它的变化。因此,首先阅读对象是内部检查,其次是查看。不确定,但它必须两次读取对象以实现$ watch magic。