2012-04-19 53 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