Backbone.js集合事件 #

一、事件概述 #

1.1 集合事件类型 #

Backbone.js集合支持多种内置事件:

text
集合事件
├── add:添加模型时触发
├── remove:移除模型时触发
├── reset:重置集合时触发
├── sort:排序时触发
├── update:集合更新时触发
├── sync:同步成功时触发
├── request:请求开始时触发
├── error:请求失败时触发
└── change:*:代理模型事件

1.2 事件继承 #

Collection继承自Events模块:

javascript
var users = new Backbone.Collection();

users.on('add', function() {
    console.log('模型已添加');
});

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

二、内置事件 #

2.1 add事件 #

javascript
var users = new Users();

users.on('add', function(model, collection, options) {
    console.log('添加了模型:', model.get('name'));
    console.log('集合大小:', collection.length);
    console.log('插入位置:', options.index);
});

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

add事件参数:

参数 说明
model 被添加的模型
collection 集合实例
options 操作选项

2.2 remove事件 #

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

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

users.remove(1);

2.3 reset事件 #

javascript
var users = new Users();

users.on('reset', function(collection, options) {
    console.log('集合已重置');
    console.log('模型数量:', collection.length);
    console.log('之前的模型:', options.previousModels);
});

users.reset([
    { id: 1, name: '张三' },
    { id: 2, name: '李四' }
]);

2.4 sort事件 #

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

var users = new Users();

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

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

2.5 update事件 #

javascript
var users = new Users();

users.on('update', function(collection, options) {
    console.log('集合已更新');
    console.log('添加的模型:', options.add);
    console.log('移除的模型:', options.removed);
    console.log('合并的模型:', options.merged);
});

users.set([
    { id: 1, name: '张三' },
    { id: 2, name: '李四' }
]);

2.6 sync事件 #

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

var users = new Users();

users.on('sync', function(collection, response, options) {
    console.log('同步成功');
    console.log('响应数据:', response);
});

users.fetch();

2.7 request事件 #

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

var users = new Users();

users.on('request', function(collection, xhr, options) {
    console.log('请求已发送');
});

users.fetch();

2.8 error事件 #

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

var users = new Users();

users.on('error', function(collection, response, options) {
    console.log('请求失败');
    console.log('状态码:', response.status);
});

users.fetch();

三、事件代理 #

3.1 模型事件代理 #

集合会自动代理模型的事件:

javascript
var users = new Users();

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

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

3.2 特定属性变化 #

javascript
var users = new Users();

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

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

3.3 模型销毁事件 #

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

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

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

users.on('destroy', function(model, collection, options) {
    console.log('模型已销毁:', model.get('name'));
});

users.at(0).destroy();

3.4 all事件 #

javascript
var users = new Users();

users.on('all', function(eventName) {
    console.log('事件:', eventName);
});

users.add({ name: '张三' });
users.at(0).set('name', '李四');

四、事件绑定方式 #

4.1 on方法 #

javascript
var users = new Users();

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

4.2 绑定多个事件 #

javascript
var users = new Users();

users.on('add remove reset', function() {
    console.log('集合已变化');
});

4.3 事件映射 #

javascript
var users = new Users();

users.on({
    'add': function(model) {
        console.log('添加:', model.get('name'));
    },
    'remove': function(model) {
        console.log('移除:', model.get('name'));
    }
});

4.4 listenTo方法 #

javascript
var UserListView = Backbone.View.extend({
    initialize: function() {
        this.listenTo(this.collection, 'add', this.addOne);
        this.listenTo(this.collection, 'remove', this.removeOne);
        this.listenTo(this.collection, 'reset', this.render);
    },
    
    addOne: function(model) {
        console.log('添加视图:', model.get('name'));
    },
    
    removeOne: function(model) {
        console.log('移除视图:', model.get('name'));
    },
    
    render: function() {
        console.log('重新渲染');
    }
});

4.5 绑定上下文 #

javascript
var users = new Users();

var handler = function(model) {
    console.log(this.message);
    console.log('添加:', model.get('name'));
};

users.on('add', handler, { message: '事件触发' });

五、事件解绑 #

5.1 off方法 #

javascript
var users = new Users();

var handler = function() {
    console.log('事件触发');
};

users.on('add', handler);
users.off('add', handler);

5.2 解绑所有事件 #

javascript
users.off();

5.3 解绑特定事件 #

javascript
users.off('add');

5.4 stopListening方法 #

javascript
var view = new Backbone.View();
var collection = new Users();

view.listenTo(collection, 'add', function() {});

view.stopListening(collection);

六、一次性事件 #

6.1 once方法 #

javascript
var users = new Users();

users.once('add', function(model) {
    console.log('只触发一次:', model.get('name'));
});

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

6.2 listenToOnce方法 #

javascript
var view = new Backbone.View();
var collection = new Users();

view.listenToOnce(collection, 'sync', function() {
    console.log('首次同步完成');
});

七、自定义事件 #

7.1 触发自定义事件 #

javascript
var Users = Backbone.Collection.extend({
    model: User,
    
    activateAll: function() {
        this.each(function(user) {
            user.set('active', true);
        });
        this.trigger('activated:all', this);
    }
});

var users = new Users();

users.on('activated:all', function(collection) {
    console.log('所有用户已激活');
});

users.activateAll();

7.2 事件命名空间 #

javascript
var users = new Users();

users.on('user:created', function() {});
users.on('user:deleted', function() {});
users.on('user:updated', function() {});

users.trigger('user:created');

7.3 传递参数 #

javascript
var users = new Users();

users.on('search', function(query, results) {
    console.log('搜索:', query);
    console.log('结果数量:', results.length);
});

users.trigger('search', '张三', [{ name: '张三' }]);

八、实用示例 #

8.1 事件驱动的列表视图 #

javascript
var TodoListView = Backbone.View.extend({
    el: '#todo-list',
    
    initialize: function() {
        this.listenTo(this.collection, 'add', this.addOne);
        this.listenTo(this.collection, 'remove', this.removeOne);
        this.listenTo(this.collection, 'change:completed', this.updateStatus);
        this.listenTo(this.collection, 'reset', this.render);
        this.listenTo(this.collection, 'filter', this.render);
    },
    
    addOne: function(todo) {
        var view = new TodoView({ model: todo });
        this.$el.append(view.render().el);
    },
    
    removeOne: function(todo) {
        this.$('#todo-' + todo.id).remove();
    },
    
    updateStatus: function(todo) {
        var $el = this.$('#todo-' + todo.id);
        $el.toggleClass('completed', todo.get('completed'));
    },
    
    render: function() {
        this.$el.empty();
        this.collection.each(this.addOne, this);
        return this;
    }
});

8.2 状态管理 #

javascript
var StatefulCollection = Backbone.Collection.extend({
    initialize: function() {
        this.state = 'idle';
    },
    
    fetch: function(options) {
        this.state = 'loading';
        this.trigger('state:change', this.state);
        
        var self = this;
        options = options || {};
        
        var success = options.success;
        options.success = function() {
            self.state = 'ready';
            self.trigger('state:change', self.state);
            if (success) success.apply(this, arguments);
        };
        
        var error = options.error;
        options.error = function() {
            self.state = 'error';
            self.trigger('state:change', self.state);
            if (error) error.apply(this, arguments);
        };
        
        return Backbone.Collection.prototype.fetch.call(this, options);
    }
});

8.3 变化追踪 #

javascript
var TrackableCollection = Backbone.Collection.extend({
    initialize: function() {
        this.changes = {
            added: [],
            removed: [],
            modified: []
        };
        
        this.on('add', function(model) {
            this.changes.added.push(model.id);
        });
        
        this.on('remove', function(model) {
            this.changes.removed.push(model.id);
        });
        
        this.on('change', function(model) {
            if (this.changes.modified.indexOf(model.id) === -1) {
                this.changes.modified.push(model.id);
            }
        });
    },
    
    getChanges: function() {
        return this.changes;
    },
    
    clearChanges: function() {
        this.changes = {
            added: [],
            removed: [],
            modified: []
        };
    }
});

8.4 事件日志 #

javascript
var LoggedCollection = Backbone.Collection.extend({
    initialize: function() {
        this.on('all', function(eventName) {
            console.log('[Collection Event]', eventName, {
                timestamp: new Date().toISOString(),
                length: this.length
            });
        });
    }
});

九、总结 #

9.1 事件方法 #

方法 说明
on(event, callback, context) 绑定事件
off(event, callback) 解绑事件
trigger(event, *args) 触发事件
once(event, callback, context) 绑定一次性事件
listenTo(obj, event, callback) 监听其他对象事件
stopListening(obj, event, callback) 停止监听

9.2 集合事件 #

事件 触发时机
add 添加模型时
remove 移除模型时
reset 重置集合时
sort 排序时
update 更新集合时
sync 同步成功时
request 请求开始时
error 请求失败时
change:* 模型属性变化时
destroy 模型销毁时

9.3 最佳实践 #

  1. 使用 listenTo 绑定事件,便于内存管理
  2. 及时解绑不再需要的事件
  3. 使用事件命名空间组织事件
  4. 利用事件代理简化代码
  5. 避免在事件回调中直接修改集合
最后更新:2026-03-28