首先我想说的是这篇文章的题目起的很怪,因为我不知道起个什么名字比较好。渲染列表是我们应用中最常见的操作了吧,在运用Backbone的应用中,我们一般会把列表作为一个Collcetion,然后指定一个View去显示这个Collection,很方便。但当你需要对一个集合进行过滤操作,只显示Collection中符合条件的那部分呢?

渲染一个内存中存在的Collection毫无疑问很简单,因为Backbone提供了一些操作的方法。但是当对一个Collection进行过滤操作之后,渲染过滤之后的结果你就会遇到一些意想不到的困难。本文将会寻找简单的代码来解决这个问题。

基本的过滤操作

Backbone.Collection有一些方法来实现过滤和搜索。其中大多数都是继承自Underscore.js,但有些不是。然而不管它们从哪里来,大部分的这些方法都有一个共同点:返回Collection中的Models数组

例如where方法,当调用这个方法的时候会返回具有你指定的属性值的Model数组。

var testCollection = new Backbone.Collection([
{name: "joy", age: 21},
{name: "jack", age: 20},
{name: "pater", age: 32},
{name: "daivd", age: 22},
{name: "gina", age: 21}
]); var results = testCollection.where({
age : 21
});

results将会是一个数组,里面有所有{age: 21}model,我们在console里面看一下:

通过视图控制过滤

显示过滤列表是相当容易的。唯一的问题是过滤操作之后返回的并不是一个Collection,而是一个Model数组。这往往会大吃一惊,捉鸡啊。怎么处理这个数组呢?如何让一个Backbone.View显示它呢?此外,当你需要显示这个过滤操作之后的数组的View已经指向了一个原始的Backbone.Collection的时候会让这个问题变得更加棘手。

你可能会说,这很容易啊,来看看下面的操作:

var FilteredView = Backbone.View.extend({

    events: {
"click #run": "runFilter"
}, runFilter: function(e){
e.preventDefault(); this.filter = {
// ... get the filter info from the DOM
}; this.render();
}, render: function(){
var html = [],
template = _.template($("tmpl-demo").html()); var filteredList = this.collection.where(this.filter); _.each(filteredList, function(item){
html.push(template(item.toJSON());
}); this.$el.html(html); return this;
}
});

在一定程度上看起来都不错。代码很短,很容易理解,也解决了问题。

但是上面的代码只符合一些简单的场景,如果你正在处理简单的情况,可能这样没有做错什么。但有存在潜伏的缺陷,当你继续需要使用过滤操作的时候,你会发现上面的代码之后没发进行进一步的过滤操作了。

怎么解决这个问题呢?让我们回到原点,我们可以对Backbone.Collection进行各种过滤操作,对,你是不是想到了什么呢?所以我们要让过滤操作之后返回的不是一个数组,而是一个Backbone.Collection对象。但是怎么实现呢?

自过滤反模式

如果你试图在原有Collection的基础上进行过滤之后再更新这个Collection,你最终会步入糟糕的境地,甚至比在View里面进行过滤操作更糟糕。

不过,还是来看看如何实现上面这种方式吧:

var testCollection = Backbone.Collection.extend({
customFilter: function(filters){
var results = this.where(filters);
this.reset(results);
}
}); var testCollection = new Backbone.Collection([
{name: "joy", age: 21},
{name: "jack", age: 20},
{name: "pater", age: 32},
{name: "daivd", age: 22},
{name: "gina", age: 21}
]); // filter the collection
testCollection.customFiler({
age : 21
});

一旦你通过自定义方法过滤Collection,Collection中便只有两个符合条件的项。这似乎是理想的结果,如果你想使用一个新的过滤器,它将只会在上次的结果中进行进一步的过滤,因为之前的Collection已经被更新了,这在大多数时候并不是我们想要的结果。

创建过滤后的Collection

如果你想用Backbone.Collection处理过滤的数组,你必须将数组转变成Backbone.Collection。这会出现两个Collection:原始的Collection和过滤之后的Collection,当你有了有了过滤后的Collection后,你就可以使用 Backbone.View来直接渲染了。

var results = testCollection.where({
age: 21
}); var filteredCollection = new Backbone.Collection(results);

是的,就是这么简单。很欢乐吧,但还是可以变得更加方便。

返回同种Collection

你可能想从自定义Backbone.Collection返回从一个过滤后的同类型的一个实例。

var testCollection = Backbone.Collection.extend({

    customFilter: function(filters){
var results = this.where(filters);
return new testCollection(results);
} }); var filteredCollection = testCollection.customFilter({
age: 21
});

更新过滤操作

当过滤条件改变的时候,你需要更新Collection,重新渲染。最好的操作方式是只实例化一个过滤后的Collection,当这个Collection改变的时候渲染对应的filterView

var FilteredView = Backbone.View.extend({
initialize: function(){
this.listenTo(this.collection, "reset", this.render, this);
}
}); var filteredCollection = new Backbone.Collection();
var filteredView = new FilteredView({
collection: filteredCollection
}); $("#run").click(function(e){
var filter = {
// ... new filters
};
var results = myCollection.where(filter); filteredCollection.reset(results);
});

Addition

加一点underscore的东西。

underscore的invoke方法是个很好用的方法,来看个栗子:

var demoCollection = Backbone.Collection.extend({
model: demoModel,
selected : function() {
return this.filter(function(itm) {
return itm.get('selected');
});
}
}); var selected = demoCollection.selected();

上文中我已经讲了如何把filter之后的返回数组变成Backbone.Collection的实例,但是很明显,这里返回的是数组。

下面的情况一般发生在批量操作的时候,如批量删除,我们要把所选的批量删除掉,我们可能需要访问一个api,然后把id传过去。

如果selected返回的是Backbone.Collection实例对象,我们可以直接使用pluck方法:

var ids= selected.pluck('id');
//返回id的数组

如果像上面selected只是Model数组呢?如何取到id的数组呢?

你可能通过each循环:

var ids = [];
_.each(selected, function(itm){
ids.push(itm.get('id'));
});

如果你想返回的不只是id的数组的话,each方法其实很适合,如果就想返回一项的数组的话,其实还有更简单的方法。

如果你有去看看Backbone的源码中的pluck方法,你会发现这方法其实调用的是underscore的invoke方法,因此,so easy:

ids = _.invoke(selected, 'get', 'id');

那你要从Collection批量删除的话,你也可以直接:

_.invoke(selected, 'destroy');

//http://underscorejs.org/#invoke
_.invoke(list, methodName, *arguments)

因此后面的参数也可以传多个,但是返回的是一个数组。

其实再看看underscore的源码的话,invoke方法内部调用的_.map,所以也可以用map方法去实现咯。

如何对Backbone.Collection进行过滤操作的更多相关文章

  1. Backbone Collection——数据模型集合

    如果将一个Model对象比喻成数据库中的一条记录,那么Collection就是一张数据表.它表示为一个模型集合类,用于存储和管理一系列相同类型的模型对象. 1.创建集合集合用于组织和管理多个模型,但它 ...

  2. backbone.Collection源码笔记

    Backbone.Collection backbone的Collection(集合),用来存储多个model,并且可以多这些model进行数组一样的操作,比如添加,修改,删除,排序,插入,根据索引取 ...

  3. Backbone Collection 源码简谈

    一切由一个例子引发: var Man=Backbone.Model.extend({ initilize:function(){ this.bind('change:name',function(){ ...

  4. Trident的过滤操作

    1.过滤操作 只是判断某个tuple是否保留 无需跨网络,无需跨分区 不会改变tuple的结构,只是改变tuple的数量 2.需求 过滤掉不是订单的tuple. 其中订单中包含“IBEIfeng.gi ...

  5. stark组件之过滤操作【模仿Django的admin】

    一.先看下django的admin是如何实现过滤操作 首先在配置类中顶一个list_filter的列表,把要过滤的字段作为元素写i进去就可以了 class testbook(admin.ModelAd ...

  6. Fiddler过滤操作

    Fidller,不做过多的简介,其中的过滤操作肯定是绕不过去的.直接上图.

  7. Backbone Collection

    http://yujianshenbing.iteye.com/blog/1748826 如果将一个Model对象比喻成数据库中的一条记录,那么Collection就是一张数据表.它表示为一个模型集合 ...

  8. 【SQL必知必会笔记(3)】SELECT语句的WHERE子句数据过滤操作

    上个笔记主要介绍了利用SELECT语句检索单个/多个/所有列,并利用DISTINCT关键字检索具有唯一性的值.利用LIMIT/OFFSET子句限制结果:以及利用ORDER BY子句排序检索出的数据,主 ...

  9. linux下拷贝命令中的文件过滤操作记录

    在日常的运维工作中,经常会涉及到在拷贝某个目录时要排查其中的某些文件.废话不多说,下面对这一需求的操作做一记录: linux系统中,假设要想将目录A中的文件复制到目录B中,并且复制时过滤掉源目录A中的 ...

随机推荐

  1. [官方教程] [ES4封装教程]2.使用 Easy Sysprep v4 封装 Windows XP

    (一)备份当前操作系统封装的第一步,其实是备份当前安装好的操作系统.避免我们在之后的步骤中出现问题,以至于还要重新安装操作系统,浪费时间精力.系统备份想必大家都会.对于WinXP而言,建议使用Ghos ...

  2. c++ builder xe2 (Embarcadero rad studio) 远程调试 同样适用于 delphi 远程调试 教程

    转载:http://www.cnblogs.com/zhangdongsheng/p/3411056.html 每次要远程调试的时候都要看半天的xe2英文帮助文档,今天正好有点时间,把它写下来. 一. ...

  3. BZOJ 1004

    一道奇怪的数学题.为了这道题我看了很多题解,到底还是一知半解..整个感觉就是上了一场数学课. HNOI2008 Cards 题目描述 小春现在很清闲,面对书桌上的N张牌,他决定给每张染色,目前小春只有 ...

  4. 【OpenStack】OpenStack系列4之Glance详解

    下载安装 参考:http://www.linuxidc.com/Linux/2012-08/68964.htm http://www.it165.net/os/html/201402/7246.htm ...

  5. Unique Paths | & ||

    Unique Paths I A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diag ...

  6. (转)JAVA AJAX教程第一章-初始AJAX

    既然是认识AJAX,理论和实践相结合,这样让自己学的更快,理解更深入,我分一下几点: 1.  认识传统的同步交互方式和AJAX解决方案 2.  AJAX使用到的技术 3.  实例体验AJAX 一.同步 ...

  7. java获取本机IP地址

    转载自:http://blog.csdn.net/thunder09/article/details/5360251 在网上找了几个用java获取本机IP地址的代码,发现都少都有些不完美,自己整理了一 ...

  8. 设置IIS会话过期时间

    打开默认网站----双击ASP--展开会话属性---更改超时时间-

  9. C语言中的break、continue和goto三者的区别与用法

    exit的话是在stdlib的头文件里面定义的,他是的程序退出,正如exit的字面意思一样break的话是终止当前循环继续进行循环后面的语句,但是程序照样还在进行只能while switch for中 ...

  10. 手机/平板 连接局域网访问局域网电脑Web服务器进行移动端页面测试

    1.开启本地服务器(我用的是XAMPP) 2.查看本机IP Mac:点击左上角的苹果标志,选择系统偏好设置,弹出系统偏好设置面板-----点击网络,选择高级,切换到tcp/ip 选项卡 会看到本机IP ...