Backbone.js集合基础 #

一、什么是Collection #

Collection(集合)是Backbone.js中用于管理多个模型实例的组件。

1.1 Collection的作用 #

text
Collection职责
├── 模型管理:管理多个模型实例
├── 批量操作:批量获取、创建、删除
├── 排序过滤:排序、过滤、查找模型
├── 事件代理:代理模型事件
└── 数据同步:与服务器批量同步数据

1.2 Collection与Model的关系 #

text
Collection (Users)
    │
    ├── Model (User) { id: 1, name: '张三' }
    │
    ├── Model (User) { id: 2, name: '李四' }
    │
    └── Model (User) { id: 3, name: '王五' }

二、创建Collection #

2.1 基本创建方式 #

javascript
var User = Backbone.Model.extend({
    defaults: {
        name: '',
        email: ''
    }
});

var Users = Backbone.Collection.extend({
    model: User
});

var users = new Users();

2.2 初始化时添加模型 #

javascript
var users = new Users([
    { name: '张三', email: 'zhangsan@example.com' },
    { name: '李四', email: 'lisi@example.com' },
    { name: '王五', email: 'wangwu@example.com' }
]);

console.log(users.length);

2.3 initialize方法 #

javascript
var Users = Backbone.Collection.extend({
    model: User,
    
    initialize: function(models, options) {
        console.log('集合初始化');
        console.log('初始模型:', models);
        console.log('选项:', options);
    }
});

var users = new Users([{ name: '张三' }], { customOption: 'value' });

2.4 指定模型类型 #

javascript
var User = Backbone.Model.extend({});
var Admin = Backbone.Model.extend({});

var Users = Backbone.Collection.extend({
    model: function(attrs, options) {
        if (attrs.role === 'admin') {
            return new Admin(attrs, options);
        }
        return new User(attrs, options);
    }
});

三、模型属性 #

3.1 model属性 #

javascript
var Users = Backbone.Collection.extend({
    model: User
});

console.log(Users.prototype.model === User);

3.2 modelId方法 #

javascript
var User = Backbone.Model.extend({
    idAttribute: '_id'
});

var Users = Backbone.Collection.extend({
    model: User,
    
    modelId: function(attrs) {
        return attrs._id;
    }
});

var users = new Users([
    { _id: 1, name: '张三' },
    { _id: 2, name: '李四' }
]);

console.log(users.get(1));

四、基本操作 #

4.1 添加模型 #

javascript
var users = new Users();

users.add({ name: '张三' });
users.add({ name: '李四' });
users.add({ name: '王五' });

console.log(users.length);

4.2 批量添加 #

javascript
var users = new Users();

users.add([
    { name: '张三' },
    { name: '李四' },
    { name: '王五' }
]);

console.log(users.length);

4.3 添加到指定位置 #

javascript
var users = new Users([
    { id: 1, name: '张三' },
    { id: 2, name: '李四' }
]);

users.add({ id: 3, name: '王五' }, { at: 0 });

console.log(users.at(0).get('name'));

4.4 移除模型 #

javascript
var users = new Users([
    { id: 1, name: '张三' },
    { id: 2, name: '李四' }
]);

var user = users.at(0);
users.remove(user);

console.log(users.length);

4.5 批量移除 #

javascript
var users = new Users([
    { id: 1, name: '张三' },
    { id: 2, name: '李四' },
    { id: 3, name: '王五' }
]);

users.remove([users.at(0), users.at(1)]);

console.log(users.length);

4.6 通过ID移除 #

javascript
var users = new Users([
    { id: 1, name: '张三' },
    { id: 2, name: '李四' }
]);

users.remove(1);

console.log(users.length);

4.7 重置集合 #

javascript
var users = new Users([
    { id: 1, name: '张三' }
]);

users.reset([
    { id: 2, name: '李四' },
    { id: 3, name: '王五' }
]);

console.log(users.length);
console.log(users.at(0).get('name'));

4.8 清空集合 #

javascript
var users = new Users([
    { id: 1, name: '张三' },
    { id: 2, name: '李四' }
]);

users.reset();

console.log(users.length);

五、查询方法 #

5.1 get方法 #

javascript
var users = new Users([
    { id: 1, name: '张三' },
    { id: 2, name: '李四' }
]);

var user = users.get(1);
console.log(user.get('name'));

5.2 at方法 #

javascript
var users = new Users([
    { id: 1, name: '张三' },
    { id: 2, name: '李四' }
]);

var user = users.at(0);
console.log(user.get('name'));

5.3 first和last #

javascript
var users = new Users([
    { id: 1, name: '张三' },
    { id: 2, name: '李四' },
    { id: 3, name: '王五' }
]);

console.log(users.first().get('name'));
console.log(users.last().get('name'));

5.4 find方法 #

javascript
var users = new Users([
    { id: 1, name: '张三', age: 25 },
    { id: 2, name: '李四', age: 30 },
    { id: 3, name: '王五', age: 25 }
]);

var user = users.find(function(user) {
    return user.get('age') === 25;
});

console.log(user.get('name'));

5.5 filter方法 #

javascript
var users = new Users([
    { id: 1, name: '张三', age: 25 },
    { id: 2, name: '李四', age: 30 },
    { id: 3, name: '王五', age: 25 }
]);

var youngUsers = users.filter(function(user) {
    return user.get('age') < 30;
});

console.log(youngUsers.length);

5.6 where方法 #

javascript
var users = new Users([
    { id: 1, name: '张三', age: 25, role: 'user' },
    { id: 2, name: '李四', age: 30, role: 'admin' },
    { id: 3, name: '王五', age: 25, role: 'user' }
]);

var result = users.where({ age: 25, role: 'user' });
console.log(result.length);

5.7 findWhere方法 #

javascript
var users = new Users([
    { id: 1, name: '张三', age: 25 },
    { id: 2, name: '李四', age: 30 }
]);

var user = users.findWhere({ age: 25 });
console.log(user.get('name'));

5.8 contains方法 #

javascript
var users = new Users([
    { id: 1, name: '张三' }
]);

var user = users.at(0);

console.log(users.contains(user));
console.log(users.includes(user));

六、集合属性 #

6.1 length属性 #

javascript
var users = new Users([
    { id: 1, name: '张三' },
    { id: 2, name: '李四' }
]);

console.log(users.length);

6.2 models属性 #

javascript
var users = new Users([
    { id: 1, name: '张三' },
    { id: 2, name: '李四' }
]);

console.log(users.models);

6.3 遍历集合 #

javascript
var users = new Users([
    { id: 1, name: '张三' },
    { id: 2, name: '李四' }
]);

users.each(function(user) {
    console.log(user.get('name'));
});

6.4 map方法 #

javascript
var users = new Users([
    { id: 1, name: '张三' },
    { id: 2, name: '李四' }
]);

var names = users.map(function(user) {
    return user.get('name');
});

console.log(names);

6.5 pluck方法 #

javascript
var users = new Users([
    { id: 1, name: '张三', age: 25 },
    { id: 2, name: '李四', age: 30 }
]);

var names = users.pluck('name');
var ages = users.pluck('age');

console.log(names);
console.log(ages);

6.6 invoke方法 #

javascript
var User = Backbone.Model.extend({
    sayHello: function() {
        return 'Hello, ' + this.get('name');
    }
});

var Users = Backbone.Collection.extend({
    model: User
});

var users = new Users([
    { name: '张三' },
    { name: '李四' }
]);

var greetings = users.invoke('sayHello');
console.log(greetings);

七、URL配置 #

7.1 url属性 #

javascript
var Users = Backbone.Collection.extend({
    model: User,
    url: '/api/users'
});

var users = new Users();
console.log(users.url);

7.2 url方法 #

javascript
var Users = Backbone.Collection.extend({
    model: User,
    
    url: function() {
        return '/api/' + this.type + '/users';
    }
});

var users = new Users();
users.type = 'admin';
console.log(users.url());

7.3 模型URL #

javascript
var User = Backbone.Model.extend({
    urlRoot: '/api/users'
});

var Users = Backbone.Collection.extend({
    model: User,
    url: '/api/users'
});

var users = new Users();
var user = users.add({ id: 1 });

console.log(user.url());

八、数据同步 #

8.1 fetch方法 #

javascript
var Users = Backbone.Collection.extend({
    model: User,
    url: '/api/users'
});

var users = new Users();

users.fetch({
    success: function(collection, response) {
        console.log('获取成功');
        console.log('模型数量:', collection.length);
    },
    error: function(collection, response) {
        console.log('获取失败');
    }
});

8.2 fetch选项 #

javascript
users.fetch({
    data: { page: 1, limit: 10 },
    reset: true,
    remove: false,
    merge: true,
    parse: true
});

选项说明:

选项 默认值 说明
data null 请求参数
reset false 是否重置集合
remove true 是否移除不存在的模型
merge true 是否合并已存在的模型
parse true 是否解析响应数据

8.3 create方法 #

javascript
var Users = Backbone.Collection.extend({
    model: User,
    url: '/api/users'
});

var users = new Users();

users.create({ name: '张三', email: 'zhangsan@example.com' }, {
    success: function(model) {
        console.log('创建成功:', model.id);
    }
});

8.4 create选项 #

javascript
users.create({ name: '张三' }, {
    wait: true,
    validate: true,
    success: function() {},
    error: function() {}
});

九、集合事件 #

9.1 add事件 #

javascript
var users = new Users();

users.on('add', function(model, collection, options) {
    console.log('添加了模型:', model.get('name'));
});

users.add({ name: '张三' });

9.2 remove事件 #

javascript
var users = new Users([{ id: 1, name: '张三' }]);

users.on('remove', function(model, collection, options) {
    console.log('移除了模型:', model.get('name'));
});

users.remove(1);

9.3 reset事件 #

javascript
var users = new Users();

users.on('reset', function(collection, options) {
    console.log('集合已重置');
});

users.reset([{ name: '张三' }]);

9.4 sort事件 #

javascript
var Users = Backbone.Collection.extend({
    model: User,
    comparator: 'name'
});

var users = new Users();

users.on('sort', function(collection, options) {
    console.log('集合已排序');
});

users.add([{ name: '王五' }, { name: '张三' }]);

9.5 事件代理 #

javascript
var users = new Users();

users.on('change:name', function(model, value) {
    console.log('模型name变化:', value);
});

var user = users.add({ name: '张三' });
user.set('name', '李四');

十、实用示例 #

10.1 分页集合 #

javascript
var PagedCollection = Backbone.Collection.extend({
    initialize: function(models, options) {
        this.page = options && options.page || 1;
        this.perPage = options && options.perPage || 10;
    },
    
    fetchPage: function(page) {
        this.page = page;
        return this.fetch({
            data: {
                page: this.page,
                perPage: this.perPage
            }
        });
    },
    
    nextPage: function() {
        return this.fetchPage(this.page + 1);
    },
    
    prevPage: function() {
        if (this.page > 1) {
            return this.fetchPage(this.page - 1);
        }
    }
});

10.2 缓存集合 #

javascript
var CachedCollection = Backbone.Collection.extend({
    initialize: function() {
        this._cache = {};
    },
    
    fetch: function(options) {
        options = options || {};
        var cacheKey = JSON.stringify(options.data || {});
        
        if (this._cache[cacheKey]) {
            this.reset(this._cache[cacheKey]);
            return $.Deferred().resolve();
        }
        
        var self = this;
        return Backbone.Collection.prototype.fetch.call(this, options)
            .done(function() {
                self._cache[cacheKey] = self.toJSON();
            });
    }
});

十一、总结 #

11.1 Collection核心API #

方法 说明
add(models, options) 添加模型
remove(models, options) 移除模型
reset(models, options) 重置集合
get(id) 通过ID获取模型
at(index) 通过索引获取模型
find(predicate) 查找模型
filter(predicate) 过滤模型
where(attrs) 条件查找
fetch(options) 从服务器获取数据
create(model, options) 创建并保存模型

11.2 最佳实践 #

  1. 始终指定 model 属性
  2. 使用 url 配置服务器接口
  3. 合理使用事件监听
  4. 使用 reset 替代批量 add
  5. 利用Underscore方法简化操作
最后更新:2026-03-28