2012-04-19 49 views
8

我在学习Backbone.js的同时正在使用Todos示例应用程序bundled with the latest version of Backbone(0.9.2)。我的问题是,为什么应用程序旨在向Todos集合中添加模型时两次触发渲染事件?Backbone.js在集合上渲染两次后添加

如果我放在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,这势必给托多斯添加事件:

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

不过是这个双渲染设计标准实践?看起来应该在创建时(或进入DOM)呈现视图,然后如果底层模型发生变化,则再次呈现视图。在这种情况下,什么都没有改变,但渲染被调用两次。

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

回答

5

嗯,有一个快速的样子。你说得对,这不是标准做法。 原因是有点模糊,所以忍受着我;)

todo应用程序正在使用backbone-localstorage。当您尝试在应用程序中添加新项目时,它会调用:

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

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

请注意Todos.create。通常,create会将模型添加到集合中,并将其保存在服务器上。因此将触发add事件。它发生虽然那骨干,localStorage的不上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事件的原因。

您可以通过更改创建办阻止这种情况发生:

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

+1

很好的捕捉!..你也可以使用'{silent:true}'来避免触发事件。 – fguillen 2012-04-19 18:18:55

+1

你说得对,这就是改变事件被解雇的原因。但是,以您建议的方式更改代码会停止该事件,但也会中断功能(我不能再删除项目)。显然,在回答我的问题方面,这并不重要,但为了防止未来有人读到这个问题,我想说明一下。 – jcady 2012-04-20 02:12:35

+0

删除项目_permanently_即。删除后,如果我刷新它们仍然存在。 – jcady 2012-04-20 02:19:20

1

重新渲染不应该发生。

尝试调试多一点。尝试将变化事件绑定到包装方法像:

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

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

要确保第二render()是为变化事件绑定,而不是为了其他原因作出。

+0

你是对的。我应该在我的问题中注意到,我最初通过将'console.log('Change!')'替换为'this.render()'来缩小这个范围。因此,我确信变化事件正在发射。 – jcady 2012-04-20 02:14:36