如何在设置多个属性时限制更改事件的数量

How to limit the number change events when multiple attributes are set?

本文关键字:事件 设置 属性      更新时间:2023-09-26

我注意到,当骨干模型的多个属性设置为这样时

model.set({
    att1:val1,
    att2:val2
});

触发两个变更事件。我错误地认为,在设置了所有属性之后,只有一个更改事件会被触发。

这看起来可能不是问题,但当函数绑定到att1时,也会使用att2的值。换句话说,当你做这个

model.bind('change:att1', func1);
...
func1 = function() {
    var att2 = model.get('att2');
}

变量att2将被设置为模型的属性att2的旧值。

问题是如何以优雅的方式防止这种情况发生。当然,一种选择是在设置att1之前设置att2,或者绑定到att2(而不是att1),但这似乎只是在简单情况下可行的选择。后一个选项还假设属性是按照set方法中列出的顺序设置的(我认为就是这样)。

我已经多次遇到这个问题,因此我提出了这个问题。问题是,我花了一些时间才意识到实际发生了什么。

最后要注意的是,就像您可以将{silent:true}作为set方法的一个选项传递一样,最好有一个选项{group:true](或类似的选项),指示只有在设置了所有属性之后才应该触发更改事件。

在更复杂的情况下,我会选择自定义事件。

我不想绑定到change:att1或change:att2,而是寻找一个特定的自定义事件,该事件是在设置了模型上要更改的所有属性后触发的。

model.set({
    att1:val1,
    att2:val2
});
model.trigger('contact:updated'); // you can chose your custom event name yourself
model.bind('contact:updated', func1);
...
func1 = function() {
    var att2 = model.get('att2');
}

这个想法的缺点是,您必须在想要触发事件的任何地方添加一行新代码。如果这种情况经常发生,你可能想更改或覆盖model.set()来为你做这件事,但你已经在更改主干代码了,不知道你对此有何感受。

编辑

在查看了主干的源代码后,我注意到change事件是在change:attribute触发之后立即触发的。(通过下面的狙击坑证明)

// Fire `change:attribute` events.
for (var attr in changes) {
  if (!options.silent) this.trigger('change:' + attr, this, changes[attr], options);
}
// Fire the `"change"` event, if the model has been changed.
if (!alreadyChanging) {
  if (!options.silent && this._changed) this.change(options);
  this._changing = false;
}

this.change(options);指的是:

change: function(options) {
  this.trigger('change', this, options);
  this._previousAttributes = _.clone(this.attributes);
  this._changed = false;
},

因此,如果您要绑定到change事件而不是特定的change:argument事件,那么在两个(或所有)属性都更改后,您将得到一个回调函数。

唯一的缺点是,即使您更改了第三个或第四个属性,它也会在ANY更改时触发。你需要在中计算

它如何在jsfiddle上工作的一个小例子http://jsfiddle.net/saelfaer/qm8xY/