Backbone.js - 更新Model上的特定属性不想触发“更改”事件

时间:2015-10-04 11:50:36

标签: javascript events backbone.js

在以下代码中,

this.listenTo(this.model, 'change:voteCount', this.changeVoteCount);
this.listenTo(this.model, 'change', this.renderTemplate);

如果“voteCount”属性更新,我想触发“this.changeVoteCount”方法,但会触发“this.renderTemplate”。

我已经谷歌搜索大约2个小时,无法找到解决方案。我该怎么办?

更新

(只是为什么我选择@ try-catch-finally回答的解释)

对于同样遇到这个问题的人,我想清除混淆应该选择哪个答案作为解决方案。

我将描述一些细节来解释为什么我选择这个答案。以下是我的模型结构:

{
   'name': 'some string',
   'location': 'some string',
   'link': 'some string',
   'voteCount': 0    }

否则“voteCount”属性已更新,我想触发“更改”事件绑定方法(在我的情况下为this.renderTemplate)。

所以我尝试了第一种方法,

this.listenTo(this.model, 'change:name change:location change:link', this.renderTemplate);

在这种方法中,如果我在一个地方同时更新“location”和“name”,那么this.renderTemplate方法将触发两次。每当“this.renderTemplate”,“location”或“name”属性单独更新或同时更新时,我希望link方法触发一次。

最后,我尝试了以下方法并取得了成功。

this.listenTo(this.model, 'change', function(model) {
            if (_.isEmpty(_.intersection(_.keys(model.changed), ["voteCount"]))) {
                this.renderTemplate.apply(this, arguments);
            }
        });

2 个答案:

答案 0 :(得分:2)

如果您不想在每个参数更改时进行渲染,您可以指定哪些参数应该触发渲染。

this.listenTo(this.model, 'change:param1 change:param2', _.debounce(this.renderTemplate));

修改:如果您不想在多个字段上多次渲染更改,则可以使用下划线debounce

b

如果在短时间内多次调用它,它将只调用一次渲染。

答案 1 :(得分:2)

除了列出您想要听取@antejan提到的更改的所有属性之外,您也可以以编程方式执行此操作。

这样您就可以检查模型的changed属性,其中包含所有已更改的属性。

this.listenTo(this.model, 'change', function(model) {
     if (!_.contains(_.keys(model.changed), "voteCount") {
          this.renderTemplate.apply(this, arguments);
     }
});

将多个键列入黑名单时,您也可以这样做:

if (_.isEmpty(_.intersection(_.keys(model.changed), ["attr1", "attr2", ...])) { ...

只要你的模型只有一些属性,我就更喜欢@antejans明确列出所有属性的方式,因为它更清晰了:

this.listenTo(this.model, "change:attr1 change:attr2 ...", this.renderTemplate);

请注意,列出多个change:attr事件可能会导致性能下降,因为Backbone会在for循环中调用侦听器。请参阅set()的{​​{3}}:

  ...

  if (!silent) {
    if (changes.length) this._pending = options;
    for (var i = 0, l = changes.length; i < l; i++) {
      this.trigger('change:' + changes[i], this, current[changes[i]], options);
    }
  }

  // You might be wondering why there's a `while` loop here. Changes can
  // be recursively nested within `"change"` events.
  if (changing) return this;
  if (!silent) {
    while (this._pending) {
      options = this._pending;
      this._pending = false;
      this.trigger('change', this, options);
    }
  }