8

在学习 Backbone.js时,我正在使用与最新版本的 Backbone (0.9.2) 捆绑在一起的 Todos 示例应用程序。我的问题是,为什么应用程序在将模型添加到 Todos 集合时会触发两次渲染事件?

如果我将此行放在 TodoView 的渲染函数中:

// Re-render the titles of the todo item.
render: function() {
  console.log("Rendering!");
  this.$el.html(this.template(this.model.toJSON()));

然后“渲染!” 在控制台中出现两次。我理解这是因为视图将模型的更改事件绑定到视图的渲染:

initialize: function() {
  this.model.bind('change', this.render, this);

并且在 addOne 中调用了 render,它绑定了 Todos 的 add 事件:

addOne: function(todo) {
  var view = new TodoView({model: todo});
  this.$("#todo-list").append(view.render().el);
},

但这就是双渲染设计的标准做法吗?看起来视图应该在创建(或进入 DOM)时呈现,然后在底层模型发生变化时再次呈现。在这种情况下,什么都没有改变,但是 render 被调用了两次。

同样,我只是在学习 Backbone,所以我可能有一个基本的误解导致我的困惑。

4

2 回答 2

5

嗯,快速浏览了一下。发生这种情况是对的,不,这不是标准做法。原因有点模糊,请耐心等待;)

待办事项应用程序正在使用主干本地存储。当您尝试在应用程序中添加新项目时,它会调用:

createOnEnter: function(e) {
  if (e.keyCode != 13) return;
  if (!this.input.val()) return;

  Todos.create({title: this.input.val()});
  this.input.val('');
},

注意Todos.create. 通常,acreate会将模型添加到集合中并将其保存在服务器上。该add事件将因此被触发。尽管主干本地存储在以下情况下会发生这种情况create

create: function(model) {
  if (!model.id) model.set(model.idAttribute, guid());
  this.data[model.id] = model;
  this.save();
  return model;
},

注意model.set给模型一个id。这就是触发(第二个)change事件的原因。

您可以通过将 create 更改为 do 来阻止这种情况发生:

if (!model.id) model.id = guid();

于 2012-04-19T15:45:04.100 回答
1

重新渲染不应该发生。

尝试调试更多。尝试将更改事件绑定到包装器方法,例如:

initialize: function(){
  this.model.bind( "change", this.renderWrapper, this );
}, 

renderWrapper: function(){
  console.log( "in the renderWrapper" );
  this.render();
}

确保第二个render()是为更改事件绑定而不是出于其他原因。

于 2012-04-19T15:09:50.710 回答