Backbone.js事件高级用法 #
一、事件命名空间 #
1.1 命名约定 #
javascript
obj.on('user:created', function() {});
obj.on('user:updated', function() {});
obj.on('user:deleted', function() {});
obj.on('order:created', function() {});
obj.on('order:updated', function() {});
1.2 层级命名 #
javascript
obj.on('app:init', function() {});
obj.on('app:user:login', function() {});
obj.on('app:user:logout', function() {});
obj.on('app:data:sync', function() {});
1.3 状态命名 #
javascript
obj.on('model:before:save', function() {});
obj.on('model:save:success', function() {});
obj.on('model:save:error', function() {});
obj.on('view:before:render', function() {});
obj.on('view:render', function() {});
obj.on('view:after:render', function() {});
二、事件代理 #
2.1 集合代理模型事件 #
javascript
var users = new Backbone.Collection();
users.on('change:name', function(model, name) {
console.log('用户姓名变化:', name);
});
var user = users.add({ name: '张三' });
user.set('name', '李四');
2.2 自定义事件代理 #
javascript
var EventProxy = {
proxyEvents: function(source, events, prefix) {
var self = this;
events.split(' ').forEach(function(event) {
self.listenTo(source, event, function() {
var args = [prefix + ':' + event].concat(
Array.prototype.slice.call(arguments)
);
self.trigger.apply(self, args);
});
});
}
};
var ChildView = Backbone.View.extend({
initialize: function() {
_.extend(this, EventProxy);
this.proxyEvents(this.model, 'change destroy', 'model');
}
});
var view = new ChildView({ model: model });
view.on('model:change', function() {
console.log('模型变化');
});
2.3 事件转发 #
javascript
var EventForwarder = {
forward: function(target, events) {
var self = this;
events.split(' ').forEach(function(event) {
self.on(event, function() {
var args = [event].concat(Array.prototype.slice.call(arguments));
target.trigger.apply(target, args);
});
});
}
};
var source = _.extend({}, Backbone.Events, EventForwarder);
var target = _.extend({}, Backbone.Events);
source.forward(target, 'alert warning error');
target.on('alert', function(msg) {
console.log('转发收到:', msg);
});
source.trigger('alert', 'Hello');
三、事件队列 #
3.1 批量触发 #
javascript
var EventEmitter = _.extend({
queue: [],
processing: false,
queueEvent: function(event) {
var args = Array.prototype.slice.call(arguments);
this.queue.push(args);
if (!this.processing) {
this.processQueue();
}
},
processQueue: function() {
if (this.queue.length === 0) {
this.processing = false;
return;
}
this.processing = true;
var args = this.queue.shift();
this.trigger.apply(this, args);
this.processQueue();
}
}, Backbone.Events);
3.2 延迟触发 #
javascript
var DelayedEmitter = _.extend({
delayedTriggers: {},
triggerDelayed: function(event, delay) {
var self = this;
var args = Array.prototype.slice.call(arguments, 2);
if (this.delayedTriggers[event]) {
clearTimeout(this.delayedTriggers[event]);
}
this.delayedTriggers[event] = setTimeout(function() {
self.trigger.apply(self, [event].concat(args));
delete self.delayedTriggers[event];
}, delay);
}
}, Backbone.Events);
3.3 防抖触发 #
javascript
var DebouncedEmitter = _.extend({
debouncedTriggers: {},
triggerDebounced: function(event, wait) {
var self = this;
var args = Array.prototype.slice.call(arguments, 2);
if (!this.debouncedTriggers[event]) {
this.debouncedTriggers[event] = _.debounce(function() {
self.trigger.apply(self, [event].concat(args));
}, wait);
}
this.debouncedTriggers[event]();
}
}, Backbone.Events);
四、事件拦截 #
4.1 前置拦截 #
javascript
var InterceptableEvents = _.extend({
interceptors: {},
before: function(event, interceptor) {
if (!this.interceptors[event]) {
this.interceptors[event] = { before: [], after: [] };
}
this.interceptors[event].before.push(interceptor);
},
trigger: function(event) {
var interceptors = this.interceptors[event];
var args = Array.prototype.slice.call(arguments, 1);
if (interceptors && interceptors.before.length > 0) {
for (var i = 0; i < interceptors.before.length; i++) {
if (interceptors.before[i].apply(this, args) === false) {
return this;
}
}
}
return Backbone.Events.trigger.apply(this, arguments);
}
}, Backbone.Events);
InterceptableEvents.before('save', function(data) {
if (!data.valid) {
console.log('拦截无效数据');
return false;
}
});
InterceptableEvents.on('save', function(data) {
console.log('保存数据:', data);
});
InterceptableEvents.trigger('save', { valid: false });
InterceptableEvents.trigger('save', { valid: true, name: '张三' });
4.2 后置处理 #
javascript
var PostProcessEvents = _.extend({
processors: {},
after: function(event, processor) {
if (!this.processors[event]) {
this.processors[event] = [];
}
this.processors[event].push(processor);
},
trigger: function(event) {
var result = Backbone.Events.trigger.apply(this, arguments);
var processors = this.processors[event];
if (processors && processors.length > 0) {
var args = Array.prototype.slice.call(arguments, 1);
processors.forEach(function(processor) {
processor.apply(this, args);
});
}
return result;
}
}, Backbone.Events);
五、事件调试 #
5.1 事件日志 #
javascript
var DebugEvents = _.extend({
debug: false,
enableDebug: function() {
this.debug = true;
},
disableDebug: function() {
this.debug = false;
},
trigger: function(event) {
if (this.debug) {
console.log('[Event]', event, Array.prototype.slice.call(arguments, 1));
}
return Backbone.Events.trigger.apply(this, arguments);
}
}, Backbone.Events);
5.2 事件追踪 #
javascript
var EventTracker = _.extend({
history: [],
maxHistory: 100,
track: function(event) {
this.history.push({
event: event,
args: Array.prototype.slice.call(arguments, 1),
timestamp: Date.now()
});
if (this.history.length > this.maxHistory) {
this.history.shift();
}
},
getHistory: function() {
return this.history;
},
getLast: function(n) {
return this.history.slice(-n);
}
}, Backbone.Events);
EventTracker.on('all', function(event) {
EventTracker.track.apply(EventTracker, arguments);
});
5.3 事件统计 #
javascript
var EventStats = _.extend({
stats: {},
record: function(event) {
if (!this.stats[event]) {
this.stats[event] = { count: 0, lastTriggered: null };
}
this.stats[event].count++;
this.stats[event].lastTriggered = Date.now();
},
getStats: function() {
return this.stats;
},
getEventCount: function(event) {
return this.stats[event] ? this.stats[event].count : 0;
}
}, Backbone.Events);
EventStats.on('all', function(event) {
EventStats.record(event);
});
六、实用示例 #
6.1 事件中间件 #
javascript
var MiddlewareEvents = _.extend({
middlewares: [],
use: function(middleware) {
this.middlewares.push(middleware);
},
trigger: function(event) {
var args = Array.prototype.slice.call(arguments);
var self = this;
var index = 0;
function next() {
if (index < self.middlewares.length) {
var middleware = self.middlewares[index++];
middleware.call(self, args, next);
} else {
Backbone.Events.trigger.apply(self, args);
}
}
next();
}
}, Backbone.Events);
MiddlewareEvents.use(function(args, next) {
console.log('中间件1:', args);
next();
});
MiddlewareEvents.use(function(args, next) {
console.log('中间件2:', args);
next();
});
MiddlewareEvents.trigger('custom', 'data');
6.2 事件订阅管理 #
javascript
var SubscriptionManager = {
subscriptions: {},
subscribe: function(obj, event, callback, context) {
var id = _.uniqueId('sub_');
this.subscriptions[id] = {
obj: obj,
event: event,
callback: callback,
context: context
};
obj.on(event, callback, context);
return id;
},
unsubscribe: function(id) {
var sub = this.subscriptions[id];
if (sub) {
sub.obj.off(sub.event, sub.callback, sub.context);
delete this.subscriptions[id];
}
},
unsubscribeAll: function() {
for (var id in this.subscriptions) {
this.unsubscribe(id);
}
}
};
6.3 条件事件 #
javascript
var ConditionalEvents = _.extend({
conditions: {},
onWhen: function(event, condition, callback, context) {
var self = this;
this.on(event, function() {
if (condition.call(context || self)) {
callback.apply(context || self, arguments);
}
}, context);
},
setCondition: function(name, condition) {
this.conditions[name] = condition;
}
}, Backbone.Events);
ConditionalEvents.setCondition('isLoggedIn', function() {
return !!localStorage.getItem('token');
});
ConditionalEvents.onWhen('action', function() {
return this.conditions.isLoggedIn();
}, function() {
console.log('已登录用户执行操作');
});
七、总结 #
7.1 高级技巧 #
| 技巧 | 说明 |
|---|---|
| 命名空间 | 组织事件结构 |
| 事件代理 | 代理其他对象事件 |
| 事件拦截 | 控制事件触发流程 |
| 事件调试 | 追踪和调试事件 |
7.2 最佳实践 #
- 使用命名空间组织事件
- 合理使用事件代理
- 实现事件拦截器控制流程
- 添加调试支持便于排查问题
- 注意事件性能,避免过度使用
最后更新:2026-03-28