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 最佳实践 #
- 使用
listenTo绑定事件,便于内存管理 - 及时解绑不再需要的事件
- 使用事件命名空间组织事件
- 利用事件代理简化代码
- 避免在事件回调中直接修改集合
最后更新:2026-03-28