Backbone.js集合排序与过滤 #
一、排序基础 #
1.1 comparator属性 #
comparator 定义集合的排序规则:
javascript
var User = Backbone.Model.extend({});
var Users = Backbone.Collection.extend({
model: User,
comparator: 'name'
});
var users = new Users([
{ id: 1, name: '王五' },
{ id: 2, name: '张三' },
{ id: 3, name: '李四' }
]);
users.each(function(user) {
console.log(user.get('name'));
});
1.2 字符串comparator #
javascript
var Users = Backbone.Collection.extend({
model: User,
comparator: 'age'
});
var users = new Users([
{ name: '张三', age: 30 },
{ name: '李四', age: 25 },
{ name: '王五', age: 28 }
]);
users.each(function(user) {
console.log(user.get('name'), user.get('age'));
});
1.3 函数comparator #
javascript
var Users = Backbone.Collection.extend({
model: User,
comparator: function(user) {
return user.get('age');
}
});
1.4 复杂排序 #
javascript
var Users = Backbone.Collection.extend({
model: User,
comparator: function(user) {
return -user.get('age');
}
});
var users = new Users([
{ name: '张三', age: 30 },
{ name: '李四', age: 25 },
{ name: '王五', age: 28 }
]);
users.each(function(user) {
console.log(user.get('name'), user.get('age'));
});
1.5 多字段排序 #
javascript
var Users = Backbone.Collection.extend({
model: User,
comparator: function(user) {
return user.get('lastName') + ' ' + user.get('firstName');
}
});
var users = new Users([
{ firstName: '三', lastName: '张' },
{ firstName: '四', lastName: '李' },
{ firstName: '五', lastName: '张' }
]);
1.6 排序函数(两个参数) #
javascript
var Users = Backbone.Collection.extend({
model: User,
comparator: function(user1, user2) {
var priority1 = user1.get('priority');
var priority2 = user2.get('priority');
if (priority1 === priority2) {
return user1.get('name').localeCompare(user2.get('name'));
}
return priority1 - priority2;
}
});
var users = new Users([
{ name: '任务A', priority: 1 },
{ name: '任务B', priority: 2 },
{ name: '任务C', priority: 1 }
]);
二、排序操作 #
2.1 sort方法 #
javascript
var users = new Users([
{ name: '王五', age: 28 },
{ name: '张三', age: 30 },
{ name: '李四', age: 25 }
]);
users.comparator = 'age';
users.sort();
users.each(function(user) {
console.log(user.get('name'), user.get('age'));
});
2.2 动态排序 #
javascript
var Users = Backbone.Collection.extend({
model: User,
sortByField: function(field, order) {
order = order || 'asc';
this.comparator = function(user) {
var value = user.get(field);
return order === 'desc' ? -value : value;
};
this.sort();
}
});
var users = new Users([
{ name: '张三', age: 30 },
{ name: '李四', age: 25 },
{ name: '王五', age: 28 }
]);
users.sortByField('age', 'desc');
2.3 静默排序 #
javascript
users.sort({ silent: true });
2.4 禁止自动排序 #
javascript
var users = new Users();
users.add({ name: '王五' }, { sort: false });
users.add({ name: '张三' }, { sort: false });
users.add({ name: '李四' }, { sort: false });
users.comparator = 'name';
users.sort();
2.5 sort事件 #
javascript
var users = new Users();
users.on('sort', function(collection, options) {
console.log('集合已排序');
});
users.comparator = 'name';
users.sort();
三、过滤基础 #
3.1 filter方法 #
javascript
var users = new Users([
{ name: '张三', age: 25, active: true },
{ name: '李四', age: 30, active: false },
{ name: '王五', age: 25, active: true }
]);
var activeUsers = users.filter(function(user) {
return user.get('active');
});
console.log(activeUsers.length);
3.2 where方法 #
javascript
var users = new Users([
{ name: '张三', age: 25, role: 'user' },
{ name: '李四', age: 30, role: 'admin' },
{ name: '王五', age: 25, role: 'user' }
]);
var result = users.where({ age: 25, role: 'user' });
console.log(result.length);
3.3 findWhere方法 #
javascript
var users = new Users([
{ name: '张三', age: 25 },
{ name: '李四', age: 30 }
]);
var user = users.findWhere({ age: 25 });
console.log(user.get('name'));
3.4 find方法 #
javascript
var users = new Users([
{ name: '张三', age: 25 },
{ name: '李四', age: 30 },
{ name: '王五', age: 25 }
]);
var user = users.find(function(user) {
return user.get('age') > 25;
});
console.log(user.get('name'));
3.5 reject方法 #
javascript
var users = new Users([
{ name: '张三', age: 25 },
{ name: '李四', age: 30 },
{ name: '王五', age: 25 }
]);
var olderUsers = users.reject(function(user) {
return user.get('age') < 30;
});
console.log(olderUsers.length);
四、高级过滤 #
4.1 复合条件过滤 #
javascript
var Users = Backbone.Collection.extend({
model: User,
filterBy: function(criteria) {
return this.filter(function(user) {
for (var key in criteria) {
if (user.get(key) !== criteria[key]) {
return false;
}
}
return true;
});
}
});
var users = new Users([
{ name: '张三', age: 25, role: 'user' },
{ name: '李四', age: 30, role: 'admin' },
{ name: '王五', age: 25, role: 'user' }
]);
var result = users.filterBy({ age: 25, role: 'user' });
console.log(result.length);
4.2 范围过滤 #
javascript
var Users = Backbone.Collection.extend({
model: User,
filterByAgeRange: function(min, max) {
return this.filter(function(user) {
var age = user.get('age');
return age >= min && age <= max;
});
}
});
var users = new Users([
{ name: '张三', age: 25 },
{ name: '李四', age: 30 },
{ name: '王五', age: 35 }
]);
var result = users.filterByAgeRange(25, 30);
console.log(result.length);
4.3 搜索过滤 #
javascript
var Users = Backbone.Collection.extend({
model: User,
search: function(query) {
query = query.toLowerCase();
return this.filter(function(user) {
var name = user.get('name').toLowerCase();
var email = user.get('email').toLowerCase();
return name.indexOf(query) !== -1 ||
email.indexOf(query) !== -1;
});
}
});
var users = new Users([
{ name: '张三', email: 'zhangsan@example.com' },
{ name: '李四', email: 'lisi@example.com' },
{ name: '王五', email: 'wangwu@example.com' }
]);
var result = users.search('张');
console.log(result.length);
4.4 正则过滤 #
javascript
var Users = Backbone.Collection.extend({
model: User,
filterByPattern: function(field, pattern) {
var regex = new RegExp(pattern, 'i');
return this.filter(function(user) {
return regex.test(user.get(field));
});
}
});
var users = new Users([
{ name: '张三', email: 'zhangsan@example.com' },
{ name: '李四', email: 'lisi@test.com' }
]);
var result = users.filterByPattern('email', '@example\\.com$');
console.log(result.length);
五、分组与统计 #
5.1 groupBy方法 #
javascript
var users = new Users([
{ name: '张三', age: 25 },
{ name: '李四', age: 30 },
{ name: '王五', age: 25 }
]);
var grouped = users.groupBy(function(user) {
return user.get('age');
});
console.log(grouped[25].length);
console.log(grouped[30].length);
5.2 countBy方法 #
javascript
var users = new Users([
{ name: '张三', role: 'user' },
{ name: '李四', role: 'admin' },
{ name: '王五', role: 'user' }
]);
var counts = users.countBy(function(user) {
return user.get('role');
});
console.log(counts);
5.3 partition方法 #
javascript
var users = new Users([
{ name: '张三', active: true },
{ name: '李四', active: false },
{ name: '王五', active: true }
]);
var partitioned = users.partition(function(user) {
return user.get('active');
});
console.log('活跃:', partitioned[0].length);
console.log('非活跃:', partitioned[1].length);
六、实用示例 #
6.1 可排序集合 #
javascript
var SortableCollection = Backbone.Collection.extend({
sortField: null,
sortOrder: 'asc',
setSort: function(field, order) {
this.sortField = field;
this.sortOrder = order || 'asc';
this.comparator = function(model) {
var value = model.get(field);
if (typeof value === 'string') {
value = value.toLowerCase();
}
return this.sortOrder === 'desc' ? -value : value;
}.bind(this);
this.sort();
},
toggleSort: function(field) {
if (this.sortField === field) {
this.sortOrder = this.sortOrder === 'asc' ? 'desc' : 'asc';
} else {
this.sortField = field;
this.sortOrder = 'asc';
}
this.setSort(field, this.sortOrder);
}
});
6.2 可过滤集合 #
javascript
var FilterableCollection = Backbone.Collection.extend({
filters: {},
setFilter: function(key, value) {
if (value === null || value === undefined) {
delete this.filters[key];
} else {
this.filters[key] = value;
}
this.trigger('filter', this.getFiltered());
},
clearFilters: function() {
this.filters = {};
this.trigger('filter', this.models);
},
getFiltered: function() {
var self = this;
return this.filter(function(model) {
for (var key in self.filters) {
if (model.get(key) !== self.filters[key]) {
return false;
}
}
return true;
});
}
});
6.3 分页集合 #
javascript
var PagedCollection = Backbone.Collection.extend({
page: 1,
perPage: 10,
getPage: function() {
var start = (this.page - 1) * this.perPage;
var end = start + this.perPage;
return this.slice(start, end);
},
setPage: function(page) {
this.page = page;
this.trigger('page:change', this.page);
},
totalPages: function() {
return Math.ceil(this.length / this.perPage);
},
hasNext: function() {
return this.page < this.totalPages();
},
hasPrev: function() {
return this.page > 1;
},
nextPage: function() {
if (this.hasNext()) {
this.setPage(this.page + 1);
}
},
prevPage: function() {
if (this.hasPrev()) {
this.setPage(this.page - 1);
}
}
});
6.4 搜索集合 #
javascript
var SearchableCollection = Backbone.Collection.extend({
searchQuery: '',
searchFields: ['name', 'email'],
search: function(query) {
this.searchQuery = query.toLowerCase();
this.trigger('search', this.getSearchResults());
},
getSearchResults: function() {
if (!this.searchQuery) {
return this.models;
}
var self = this;
return this.filter(function(model) {
return self.searchFields.some(function(field) {
var value = model.get(field);
if (value) {
return value.toLowerCase().indexOf(self.searchQuery) !== -1;
}
return false;
});
});
},
clearSearch: function() {
this.searchQuery = '';
this.trigger('search', this.models);
}
});
七、总结 #
7.1 排序方法 #
| 方法 | 说明 |
|---|---|
| comparator | 定义排序规则 |
| sort(options) | 执行排序 |
| sortBy(field) | 按字段排序 |
7.2 过滤方法 #
| 方法 | 说明 |
|---|---|
| filter(predicate) | 过滤模型 |
| where(attrs) | 条件过滤 |
| findWhere(attrs) | 查找第一个匹配 |
| find(predicate) | 查找第一个满足条件的 |
| reject(predicate) | 反向过滤 |
7.3 最佳实践 #
- 使用
comparator实现默认排序 - 使用函数形式实现复杂排序
- 封装通用的过滤方法
- 使用事件通知过滤结果变化
- 考虑性能,避免频繁排序
最后更新:2026-03-28