3

我想我正面临一个关于将值直接设置为计算属性的错误,当它的相关键再次更改时,它似乎会破坏计算,这里有一个例子:

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个错误:

  1. 一切正常,直到我直接使用“set”更新计算属性 v2,当我再次更新 v1 时,不会重新评估 v2。

  2. 当直接设置 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!!!"
4

2 回答 2

1

Ember 使用 arunloop来优化绑定并将 DOM 更新保持在最低限度。它通过将像这样的属性更改放在队列中来做到这一点。然而,队列更聪明一些。

如果你说在渲染到 DOM 之前修改一个属性 10 次,它只会使用你为该属性设置的最后一个值。因此,当您需要在 DOM 中显示该属性时,只需更新一次。

此外,计算属性是一个函数,它根据传入的参数数量同时充当 getter 和 setter。语法是,

myProperty: function(key, value) {
  if (value) {
    // setter
  } else {
    // getter
  }
}.property()

在上面的示例中,您仅返回从依赖项计算的值v1。您还需要提供一个设置器,将值v1v2计算的属性中放入。

于 2013-07-07T04:13:03.170 回答
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是一个函数,你将它设置为一个值)。为什么要重新评估?

于 2013-07-06T16:51:49.627 回答