2012-04-12 36 views
6

我正在設置由Backbone驅動的應用程序。我面臨一個「應該是簡單的」問題,我有一個名爲「Message」的模型,一個名爲「MessageList」的集合,以及名爲「MessageView」和「MessageListView」的視圖。Backbone Collection - 過濾和渲染集合失去對原始未過濾集合的引用

MessageListView代碼呈現MessageList。我有4個切換按鈕來過濾MessageListView顯示的內容。過濾器按鈕爲「全部」,「活動」,「標記」和「忽略」。 「全部」是頁面加載時的初始過濾器。當用戶按下「標記」過濾器時,只會出現帶有標記== 1的消息。當再次按下「全部」時,所有消息應再次出現。

我遇到的問題和我設計中的問題是,當我根據filterString過濾Collection時,對原始整個Collection的引用會丟失。因此,當再次按下「全部」時,消息已丟失。

我很好奇,在骨幹做到這一點的最好辦法...

這裏設置代碼...

var messageListView = new MessageListView({collection: messageList}); 

這裏的MessageListView代碼...

MessageListView = Backbone.View.extend({ 

    initialize : function() { 

     this.collection.on("add", function(model) { 
      var view = new MessageView({model: model}); 
      $("div.cameras").prepend(view.render().el); 
     }); 

     this.collection.on("remove", function(model) { 
      var ID = model.id; 
      $("#message-" + ID).parent("div.message").remove(); 
     }); 

     this.collection.on("reset", function(models) { 
      $("div.cameras").empty(); 
      models.each(function(message) { 
       var view = new MessageView({model: message}); 
       $("div.cameras").prepend(view.render().el); 
      }); 
     }); 

    }, 

    filterMessages : function(filterString) { 
     var filtered = this.collection.filter(function(model){ 

      if (filterString == "all") 
      { 
       return true; 
      } 
      else if (filterString == "active") 
      { 
       return model.get("ignore") == "0"; 
      } 
      else if (filterString == "ignore") 
      { 
       return model.get("ignore") == "1"; 
      } 
      else if (filterString == "flag") 
      { 
       return model.get("flag") == true; 
      } 

     }); 
     this.collection.reset(filtered); 
    }, 
+0

我upvoted兩個問題,答案,謝謝你們。只是提示OP:我寧願將過濾函數放在Collection中,而不是視圖。 MVC世界有這樣的說法,「胖模型,瘦身控制器」。在Backbone中,視圖充當控制器。 Backbone的系列產品擁有Underscore的功能,這一事實暗示了這一點。 – DjebbZ 2012-11-23 16:15:48

回答

10

當你調用

this.collection.reset(filtered) 

您將丟棄舊數據並將其替換爲新數據。

你想要做的是做一個臨時'集合'(數組或Backbone.Collection)來保存過濾器的結果,這就是你用來將消息呈現給「數據源」 DOM。

有幾種方法可以做到這一點。

  1. 只是在每種情況下(包括'全部'情況)呈現filterMessages函數的[array]輸出,但不要將結果反饋回原始集合。
  2. 創建第二個集合以接收filterMessages函數的結果,並再次渲染該集合,使原始集合保持不變。
4

您可以使用Backbone.CollectionView,它允許您使用visibleModelsFilter選項指定集合中哪些模型當前可見。

設置代碼...

var messageListView = new MessageListView({ 
    collection: messageList, 
    modelView : MessageView 
}); 

MessageListView代碼...

MessageListView = Backbone.CollectionView.extend({ 

    filterMessages : function(filterString) { 
     if (filterString == "all") { 
      this.setOption("visibleModelsFilter", null); 
     } 
     else if (filterString == "active") { 
      this.setOption("visibleModelsFilter", function(thisModel) { 
       return model.get("ignore") == "0"; 
      }); 
     } 
     else if (filterString == "ignore") { 
      this.setOption("visibleModelsFilter", function(thisModel) { 
       return model.get("ignore") == "1"; 
      }); 
     } 
     else if (filterString == "flag") { 
      this.setOption("visibleModelsFilter", function(thisModel) { 
       return model.get("flag") == true; 
      }); 
     } 
    } 

});