我认为我面临一个错误,即直接将值设置为计算属性,当它的相关键再次发生变化时,它似乎会破坏计算,这里有一个例子:
o = Ember.Object.extend({
v1: null,
v2: function (){
console.log('evaluation of v2', arguments);
return this.get('v1') + '!!!';
}.property('v1'),
v1_Observer: function () {
console.warn('v1 changed:', this.get('v1'));
}.observes('v1'),
v2_Observer: function (){
console.info('v2 changed:', this.get('v2'));
}.observes('v2')
});
oi = o.create();
oi.set('v1', 'Value v1 one');
oi.set('v2', 'Value direct to v2');
oi.set('v1', 'Value v1 two');
Ember.assert('v2 should be "Value v1 two!!!"', oi.get('v2') === (oi.get('v1') + '!!!'));
我认为这里有2个错误:
一切正常,直到我用“set”直接更新计算属性v2,当我再次更新v1时,v2不会被重新评估。
直接设置v2时,它的观察者被调用两次!
根据文档http://emberjs.com/guides/object-model/computed-properties/,我们可以使用'set'直接设置计算属性的值。将使用2个参数(键,值)调用!但在我的测试中,当v1第一次改变时,属性v2仅触发一次。
这是控制台的输出:
evaluation of v2 ["v2"]
v2 changed: Value v1 one!!!
v1 changed: Value v1 one
v2 changed: Value direct
v2 changed: Value direct
v1 changed: Value v1 two
Assertion failed: v2 should be "Value v1 two!!!"
答案 0 :(得分:1)
运行示例,我在控制台中看到以下内容
> oi = o.create();
> oi.set('v1', 'Value v1 one');
[Log] evaluation of v2 ["v2"]
[Log] v2 changed: Value v1 one!!!
[Warning] v1 changed: Value v1 one
> oi.set('v2', 'Value direct to v2');
[Log] v2 changed: Value direct to v2
> oi.set('v1', 'Value v1 two');
[Log] v2 changed: Value direct to v2
[Warning] v1 changed: Value v1 two
直接设置v2时列出项目,其观察者被调用两次!
你可能已经注意到,'v2'的观察者在行中被调用了两次,因为你首先设置了v1
的值,这使v2
重新计算并且观察者开火了,它当你直接设置v2
时第二次运行 - 所以没有什么好奇的。
列表项一切正常,直到我用“set”直接更新计算属性v2,当我再次更新v1时,v2不会被重新评估。
一旦手动设置v2
,你基本上就会告诉计算属性消失并用一个值替换它(实质上,v2
是一个函数,你将它设置为一个值)。为什么会重新评估?
答案 1 :(得分:1)
Ember使用runloop
来优化绑定并将DOM更新保持为最小值。它通过将这些属性更改放在队列中来实现。然而,队列更聪明一些。
如果您要在将属性呈现给DOM之前修改属性10次,它将仅使用您为该属性设置的最后一个值。因此,当您需要在DOM中显示属性时,只需要更新一次。
此外,计算属性是一个函数,它根据传入的参数数量充当getter和setter。语法是,
myProperty: function(key, value) {
if (value) {
// setter
} else {
// getter
}
}.property()
在上面的示例中,您只返回从依赖v1
计算的值。您还需要提供一个setter,将值从v1
计算属性中反馈回v2
。