自定义事件
使用 CustomEvent 和 EventTarget 创建自定义事件
问题
JavaScript 中如何创建和使用自定义事件?
解答
方式一:使用 CustomEvent
// 创建自定义事件,可以携带数据
const event = new CustomEvent('userLogin', {
detail: { userId: 123, username: 'john' },
bubbles: true, // 是否冒泡
cancelable: true // 是否可取消
});
// 监听事件
document.addEventListener('userLogin', (e) => {
console.log('用户登录:', e.detail.username);
});
// 触发事件
document.dispatchEvent(event);
方式二:使用 EventTarget 创建事件中心
// 创建独立的事件中心
const eventBus = new EventTarget();
// 监听
eventBus.addEventListener('message', (e) => {
console.log('收到消息:', e.detail);
});
// 触发
eventBus.dispatchEvent(new CustomEvent('message', {
detail: { text: 'Hello' }
}));
方式三:手写事件系统
class EventEmitter {
constructor() {
this.events = {};
}
// 订阅事件
on(event, callback) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(callback);
return this; // 支持链式调用
}
// 触发事件
emit(event, ...args) {
const callbacks = this.events[event];
if (callbacks) {
callbacks.forEach(cb => cb(...args));
}
return this;
}
// 取消订阅
off(event, callback) {
const callbacks = this.events[event];
if (callbacks) {
this.events[event] = callbacks.filter(cb => cb !== callback);
}
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('data', (msg) => console.log('收到:', msg));
emitter.emit('data', 'Hello World');
emitter.once('login', (user) => console.log('登录:', user));
emitter.emit('login', 'Alice'); // 输出: 登录: Alice
emitter.emit('login', 'Bob'); // 无输出,因为只订阅一次
关键点
CustomEvent通过detail属性传递自定义数据dispatchEvent触发事件,addEventListener监听事件EventTarget可以创建独立的事件中心,不依赖 DOM- 手写实现的核心是维护一个事件名到回调数组的映射
once的实现思路:包装回调,执行后立即移除
目录