手写 Vue 事件机制
实现 Vue 的 $on、$off、$emit、$once 方法
问题
Vue 的事件机制允许组件之间通信,需要实现 $on、$off、emit 和 $once 方法来理解其工作原理。
解答
Vue 事件机制基于发布订阅模式,通过一个事件中心来管理事件的注册、触发和销毁。
class EventEmitter {
constructor() {
this.events = {};
}
// 监听事件
$on(event, callback) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(callback);
return this;
}
// 取消监听
$off(event, callback) {
if (!this.events[event]) return this;
// 如果没有传递回调,移除该事件的所有监听
if (!callback) {
this.events[event] = [];
return this;
}
// 移除特定回调
this.events[event] = this.events[event].filter(cb => cb !== callback);
return this;
}
// 触发事件
$emit(event, ...args) {
if (!this.events[event]) return this;
this.events[event].forEach(callback => {
callback(...args);
});
return this;
}
// 只监听一次
$once(event, callback) {
const wrapper = (...args) => {
callback(...args);
this.$off(event, wrapper);
};
this.$on(event, wrapper);
return this;
}
}
使用示例:
const emitter = new EventEmitter();
// 监听事件
emitter.$on('test', (msg) => {
console.log('收到消息:', msg);
});
// 触发事件
emitter.$emit('test', 'Hello Vue'); // 输出: 收到消息: Hello Vue
// 只监听一次
emitter.$once('login', (user) => {
console.log('用户登录:', user);
});
emitter.$emit('login', 'Alice'); // 输出: 用户登录: Alice
emitter.$emit('login', 'Bob'); // 无输出
// 取消监听
const handler = () => console.log('clicked');
emitter.$on('click', handler);
emitter.$off('click', handler);
关键点
$on将回调函数存储到事件数组中,支持同一事件注册多个回调$off不传回调时移除该事件所有监听,传回调时只移除匹配的回调$emit遍历事件数组,依次执行所有回调并传递参数$once通过包装函数实现,执行后立即调用$off移除自身- 所有方法返回
this支持链式调用
目录