2012-04-12 31 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; 
      }); 
     } 
    } 

});