简单的事件总线或发布订阅模式
class Event {
constructor() {
this.events = {}
}
subscribe(event, handler) {
this.events[event] = this.events[event] || []
this.events[event].push(handler)
return () => this.unSubscribe(event, handler)
}
unSubscribe(event, handler) {
let handlers = this.events[event]
if (handlers && Array.isArray(handlers)) {
for (let i = 0; i < handlers.length; i++) {
if (handlers[i] === handler) {
handlers.splice(i, 1)
break
}
}
}
}
emit(event, ...args) {
;(this.events[event] || []).forEach((handler) => {
handler(...args)
})
}
}
使用方法
// 在你的应用中创建一个全局实例
let globalEvent = new Event()
let handler1 = (data) => console.log(`handler1(): FOO事件触发,数据: ${data}`)
let handler2 = (data) => console.log(`handler2(): FOO事件触发,数据: ${data}`)
// 订阅事件
globalEvent.subscribe('FOO', handler1)
globalEvent.subscribe('FOO', handler2)
// 在需要时触发事件
globalEvent.emit('FOO', 'foo')
// 预期输出:
// handler1(): FOO事件触发,数据: foo
// handler2(): FOO事件触发,数据: foo
// 取消订阅事件
globalEvent.unSubscribe('FOO', handler2)
// 然后
globalEvent.emit('FOO', 'bar')
// 预期输出:
// handler1(): FOO事件触发,数据: bar
高级功能
一次性订阅
添加只执行一次的事件订阅:
class EventEmitter {
constructor() {
this.events = {}
}
subscribe(event, handler) {
this.events[event] = this.events[event] || []
this.events[event].push(handler)
// 返回取消订阅函数
return () => this.unSubscribe(event, handler)
}
// 一次性订阅
once(event, handler) {
const onceHandler = (...args) => {
handler(...args)
this.unSubscribe(event, onceHandler)
}
return this.subscribe(event, onceHandler)
}
unSubscribe(event, handler) {
let handlers = this.events[event]
if (handlers && Array.isArray(handlers)) {
for (let i = 0; i < handlers.length; i++) {
if (handlers[i] === handler) {
handlers.splice(i, 1)
break
}
}
}
}
// 清除所有事件监听器
clear(event) {
if (event) {
delete this.events[event]
} else {
this.events = {}
}
}
emit(event, ...args) {
;(this.events[event] || []).forEach((handler) => {
try {
handler(...args)
} catch (error) {
console.error(`事件处理器错误:`, error)
}
})
}
// 获取事件的监听器数量
listenerCount(event) {
return (this.events[event] || []).length
}
}
使用示例
const eventBus = new EventEmitter()
// 基础订阅
const unsubscribe = eventBus.subscribe('user-login', (user) => {
console.log(`用户 ${user.name} 已登录`)
})
// 一次性订阅
eventBus.once('app-ready', () => {
console.log('应用初始化完成')
})
// 触发事件
eventBus.emit('user-login', { name: 'John', id: 123 })
eventBus.emit('app-ready')
// 取消订阅
unsubscribe()
// 查看监听器数量
console.log(eventBus.listenerCount('user-login')) // 0
实际应用场景
组件通信
// 在React或Vue组件中使用
class ComponentA {
constructor() {
this.eventBus = globalEvent
}
sendMessage() {
this.eventBus.emit('message', '来自组件A的消息')
}
}
class ComponentB {
constructor() {
this.eventBus = globalEvent
this.eventBus.subscribe('message', this.handleMessage.bind(this))
}
handleMessage(message) {
console.log('组件B收到消息:', message)
}
}
状态管理
// 简单的状态管理
class SimpleStore {
constructor() {
this.state = {}
this.events = new EventEmitter()
}
setState(newState) {
this.state = { ...this.state, ...newState }
this.events.emit('state-change', this.state)
}
subscribe(callback) {
return this.events.subscribe('state-change', callback)
}
}
优势
- 轻量级: 无需外部依赖
- 简单易用: API清晰直观
- 解耦: 组件间松耦合通信
- 灵活: 支持多个监听器和参数传递
注意事项
- 避免内存泄漏:记得取消不需要的订阅
- 错误处理:在事件处理器中添加错误处理
- 命名规范:使用清晰的事件名称
- 调试支持:可以添加调试日志功能