【问题标题】:Computed Property not updating after direct set直接设置后计算属性不更新
【发布时间】:2013-07-06 16:34:18
【问题描述】:

我认为我面临一个错误,即直接将值设置为计算属性,当相关键再次更改时似乎会破坏计算,这里是一个示例:

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个参数(键,值)调用!但在我的测试中,属性 v2 仅在 v1 第一次更改时触发一次。

这是控制台的输出:

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!!!"

【问题讨论】:

    标签: ember.js


    【解决方案1】:

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

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

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

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

    在上面的示例中,您只返回从依赖 v1 计算的值。您还需要提供一个 setter,将来自 v2 计算属性的值返回到 v1。

    【讨论】:

      【解决方案2】:

      运行您的示例,我在控制台中看到以下内容

      > 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 是一个函数,你将它设置为一个值)。为什么要重新评估?

      【讨论】:

      • 感谢您的回答...如果您注意到,“v2”观察者被调用了 3 次,设置“v1”时调用一次,直接设置“v2”时调用两次,这就是我不知道的期望,从代码中,如果我理解得很好,“v2”观察者应该调用 3 次:一次当我设置“v1”时,一次当我设置“v2”时,一次当我再次设置“v1”时,它的最终值应该是“价值 v1 2!!!”
      • 我的理解是,实际上它应该被调用了两次,最终的值应该是“Value direct to v2”。第三次调用它可能是一个错误,但最终的值应该是它。
      • 在我的理解中,设置 v1 应该总是使 v2 为 r-eval,即使我之前直接修改了 v2 !如果你说的是真的!手动更改 v2 应该始终通过设置 v1 来通过,相反我们应该使用观察者来更改某些值而不是计算!
      • 我用属性 isValid 提出的案例女巫评估以验证输入,但有时我需要强制 isValid,但当输入再次更改时 isValid 需要重新评估!如果 ember 不是为此而设计的,则可能需要将其包含在文档中。
      • 当您手动设置v2 时,它不再是计算属性,它是正确的行为。如果你想强制一些属性,你可以设置一些其他属性(比如forceValid)并在isValid中检查它来做你想做的事。
      猜你喜欢
      • 2016-04-22
      • 2019-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-15
      • 1970-01-01
      • 2019-10-19
      相关资源
      最近更新 更多