@ohqnqho/emiter-js
v2.0.1
Published
Tiny typed event emitter
Maintainers
Readme
@ohqnqho/emiter-js
零依赖的 TypeScript 事件总线。支持 ESM / CJS / TypeScript 类型,可按模块创建独立实例。
安装
npm install @ohqnqho/emiter-jsNode.js >= 20。自带 .d.ts,TypeScript 项目无需额外类型包。
引入
ESM:
import emiter, { Emitter } from '@ohqnqho/emiter-js'CommonJS:
const { Emitter, emiter } = require('@ohqnqho/emiter-js')浏览器 CDN(全局是 类 Emiter):
<script src="https://unpkg.com/@ohqnqho/emiter-js"></script>
<script>
const bus = new Emiter()
bus.on('tick', (n) => console.log(n))
bus.emit('tick', 1)
</script>模块化
每个 new Emitter() 都有自己的监听表,互不影响。默认导出的 emiter 是可选单例,适合小脚本;业务模块请自己建实例。
import emiter, { Emitter } from '@ohqnqho/emiter-js'
// 模块 A
const chat = new Emitter()
chat.on('message', (text) => render(text))
// 模块 B,和 chat / 全局单例都不共享
const ui = new Emitter()
ui.emit('message', '不会进 chat')
// 可选:进程内全局总线
emiter.emit('boot')TypeScript
传入事件表后,事件名和 payload 都会收紧。值为 void 的事件可以不传 payload。
import { Emitter } from '@ohqnqho/emiter-js'
type AppEvents = {
ready: void
message: string
progress: { pct: number }
}
const bus = new Emitter<AppEvents>()
bus.emit('ready')
bus.emit('message', 'hi')
bus.on('progress', ({ pct }) => {
console.log(pct)
})
// bus.emit('message') // 类型错误:缺少 payload
// bus.emit('missing') // 类型错误:未知事件不传泛型时按 Record<string, any> 处理,JavaScript 用法不受影响。
也可只导入类型:
import type { Emitter, EventMap, Handler, ListenOptions } from '@ohqnqho/emiter-js'API
on / once 返回取消函数。off 按函数、按 { key }、按事件名、或全部清空。
const stop = bus.on('tick', (n) => console.log(n))
bus.once('ready', () => {})
bus.emit('tick', 1)
stop()
bus.off('tick', handler)
bus.off('tick', { key: 'sidebar' })
bus.off('tick')
bus.off()
bus.listenerCount('tick')
bus.listenerCount()命名槽 { key }
同一事件上相同 key 会替换旧监听,旧的 unsubscribe 变成空操作。适合组件反复绑定、又不想握住上一次的函数引用。
bus.on('resize', handlerA, { key: 'sidebar' })
bus.on('resize', handlerB, { key: 'sidebar' }) // 替换 handlerA
bus.off('resize', { key: 'sidebar' })key 按事件隔离:'a' / 'slot' 和 'b' / 'slot' 互不影响。
行为
- 同一函数无
key注册两次,就是两条独立订阅。off(event, fn)会去掉该函数的全部条目。 emit先对监听列表做快照:本轮里新on的不跑;本轮里被off但仍在快照中的仍会跑。once在调用前从列表移除。抛错的once也算已消费。- handler 抛错不捕获,本轮后续监听跳过。没有
'error'事件。 - handler 不绑定
this。未知事件的emit/off是空操作,不抛错。 - 单参数 payload,不是
...args。
