2012-03-06 100 views
6

是否有直接的方式將新模型項插入backbone.js Collection的中間,然後更新集合的View以將新項目包含在正確的位置?將項目插入backbone.js集合

我正在從一個列表中添加/刪除項目。每個列表項目都有自己的ModelView,並且我也有整個集合的View

每個項目視圖都有一個Duplicate按鈕,用於克隆項目的模型並將其插入到被點擊項目下方索引位置的集合中。

將項目插入集合很簡單,但我無法弄清楚如何更新集合視圖。我一直是這樣的:

ListView = Backbone.View.extend({ 
    el: '#list-rows', 
    initialize: function() { 
     _.bindAll(this); 
     this.collection = new Items(); 
     this.collection.bind('add', this.addItem); 
     this.render(); 
    }, 
    render: function() { 
     this.collection.each(this.addItems); 
     return this; 
    }, 
    addItem: function (item) { 
     var itemView = new ItemView({ model: item }), 
      rendered = itemView.render().el, 
      index = this.collection.indexOf(item), 
      rows = $('.item-row'); 

     if (rows.length > 1) { 
     $(rows[index - 1]).after(rendered); 
     } else { 
     this.$el.append(rendered); 
     } 
    } 
} 

這個實現類的工作,但我發現了奇怪的錯誤,當我添加一個新的項目。我敢肯定,我可以把它們整理出來,但是......

我腦海中有一種聲音不斷告訴我有更好的方法來做到這一點。不得不手動確定在哪裏插入新的ItemView看起來真的很不習慣 - 不應該收集視圖知道如何重新集合已經收集?

有什麼建議嗎?

回答

4

我正在做的通常方法是讓ListView呈現其函數中的每個ItemView函數。然後,我只是add事件綁定到render功能,像這樣:

你叫 this.collection.add(someModel, {at: index})
ListView = Backbone.View.extend({ 
    el: '#list-rows' 
    , initialize: function() { 
    _.bindAll(this); 
    this.collection = new Items(); 
    this.collection.bind('add', this.render); 
    this.render(); 
    } 
    , render: function() { 
    this.$el.empty(); 
    var self = this; 
    this.collection.each(function(item) { 
     self.$el.append(new ItemView({ model: item }).render().el); 
    }); 
    return this; 
    } 
} 

每次,視圖將相應重新呈現。

+0

我不得不在'render'方法內部調用'(.item-row).remove()'來獲得這個效果,但這是一個很好的解決方案。 (否則,重新渲染的項目將被添加到現有渲染項目的末尾。)感謝您的幫助! – 2012-03-06 18:30:28

+0

哦,你可以在循環收集之前執行'this。$ el.empty()'清除'$ el' :) – sntran 2012-03-06 18:37:18

+0

這就是我現在向集合添加項目的方式。它將新項目放在集合中的正確位置。我注意到我在上面的評論中有幾個拼寫錯誤:我調用了'$('。item-row')。remove()'來清除上次集合被渲染時創建的項目。這只是重置視圖。想想看,有一種「重置」方法可以做我想做的事。我會嘗試調用它,然後調用'render'。 – 2012-03-06 18:42:44

9

我不認爲在添加新元素時重新渲染整個集合是最佳解決方案。這比在正確的地方插入新項目要慢,特別是如果列表很長。

另外,請考慮以下情況。您可以在集合中加載幾個項目,然後再添加n更多項目(比如用戶點擊「加載更多」按鈕)。爲此,您可以將fetch()方法稱爲add: true作爲選項之一。當數據從服務器收回時,'add'事件被激發n次,並且最終您將重新呈現您的列表n次。

實際上,我用你的問題的代碼的變種

,這裏是我的回調到「添加」事件:

var view, prev, prev_index; 
view = new ItemView({ model: new_item }).render().el; 
prev_index = self.model.indexOf(new_item) - 1; 
prev = self.$el.find('li:eq(' + prev_index + ')'); 
if (prev.length > 0) { 
    prev.after(view); 
} else { 
    self.$el.prepend(view); 
} 

所以,基本上我只是用:eq() jQuery選擇,而不是領所有的元素,你應該使用更少的內存。

+0

這很好,但我在列表中的每個項目旁邊都顯示數字,所以我需要重新渲染以保持數字同步。無法看到任何方式。無賴......我喜歡這裏的簡單。 – byron 2017-12-23 00:02:27