为什么在Backbone的set方法中有一个while循环?

时间:2014-12-24 02:41:59

标签: javascript backbone.js model-view-controller

Github source code

以下是Backbone设置方法的片段:

set: function(key, val, options) {
  var attr, attrs, unset, changes, silent, changing, prev, current;

  ...

  options || (options = {});

  ...

  // Trigger all relevant attribute changes.
  if (!silent) {
    if (changes.length) this._pending = options;
    for (var i = 0, length = changes.length; i < length; 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);
    }
  }
  this._pending = false;
  this._changing = false;
  return this;
}

虽然评论确实提到了我想知道的while循环,但我没有看到这个while循环是如何工作的,因为局部变量changing始终是true一轮set

有人可以向我解释为什么会有一段时间,什么时候会生效?

提前致谢!

1 个答案:

答案 0 :(得分:1)

正如评论所说,&#34;更改可以递归嵌套在"change"个事件中。&#34;

"change"事件被触发时,更新或重新设置模型上的某些属性并不是取消注释,而是再次调用set_pending属性就是为了确保在"change"上更新的所有属性实际上都已更改。

看起来他们曾经检查过是否有其他更改,以及是否有用于触发just 1 change event的主干。这样做的问题是,如果有更新事件的监听器更新多个属性,则不会调用所有set函数。有关具体示例,请参阅this unit test。因此while循环处理1个侦听器多次调用set的边缘情况,而不是多个侦听器,每次调用set一次。像上面链接的测试中的这个:

model.on('change:a', function() {
  model.set({b: true});
  model.set({b: true});
});

如果您对将this._pending更改为选项的原因感到困惑,请查看this issue&amp; the associated pull request