# Emitter > 订阅/发布 基础工具包 | Statements | Branches | Functions | Lines | | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | | ![Statements](https://img.shields.io/badge/statements-91.78%25-brightgreen.svg?style=flat) | ![Branches](https://img.shields.io/badge/branches-94.5%25-brightgreen.svg?style=flat) | ![Functions](https://img.shields.io/badge/functions-94.33%25-brightgreen.svg?style=flat) | ![Lines](https://img.shields.io/badge/lines-91.78%25-brightgreen.svg?style=flat) | ## API | Fn | 参数 | 说明 | | ----- | ------------------------ | ---------- | | $emit | (type, data, expands) | 发布 | | $on | (type, handler, expands) | 订阅 | | $once | (type, handler, expands) | 仅订阅单次 | | $off | (type, handler, expands) | 取消订阅 | ### 参数 | 参数 | 类型 | 说明 | | ----------------------- | ------------------------------ | ------------------------------------------ | | type | String | 事件标识 | | data | Any | 事件数据 | | handler | Function (data, expands, type) | 订阅回调函数 | | expands | Object | 扩展参数 | | expands.cross | Boolean | 是否发布跨标签页事件 | | expands.fromCross | Boolean | 是否来自跨标签页事件 | | expands.replay | Boolean | 是否发布可回放事件(仅回放最近一次) | | expands.fromReplay | Boolean | 是否来自可回放事件 | | expands.customEvent | Boolean | 是否发布自定义事件(custom-event-emitter) | | expands.fromCustomEvent | Boolean | 是否来自自定义事件(custom-event-emitter) | ## 示例 > 更多示例请参考 `test` 目录下的测试用例 ```javascript this.$on('init', () => { // init }) this.$emit('init') ``` ### 跨标签页通信 > 跨标签页通信,需要在发布事件时设置 `cross` 参数为 `true` ⚠️ 注意:会同时触发本页面的 $on() 监听及其他页面的 $on() 监听,如需不触发本页面的 $on() 监听,请在 $on 回调中单独判断 expands.`fromCross` ```javascript this.$on('init', (data, expands) => { // 是否来自跨标签页事件 if (expands?.fromCross) { } }) this.$emit('init', { cross: true }) ``` ### 可回放事件 > 可回放事件,需要在发布事件时设置 `replay` 参数为 `true` ```javascript const emitter = new Emitter({ replay: true, logger: false, cross: false, customEvent: false }) const testContent = 'test-replay' let result = null emitter.$emit(testContent, testContent, { replay: true }) emitter.$on(testContent, (event, expands) => { result = event // expect(expands.replay).toBe(true) // expect(expands.fromReplay).toBe(true) }) // expect(result).toBe(testContent) emitter.$off(testContent) ``` ### 自定义事件 > 自定义事件,需要在发布事件时设置 `customEvent` 参数为 `true` 默认用于 addListener, dispatchEvent 通信的event: ** custom-event-emitter ** ⚠️ 注意:会同时触发本页面的 $on() 监听,如需不触发本页面的 $on() 监听,请在 $on 回调中单独判断 expands.`fromCustomEvent` ```javascript const emitter = new Emitter({ replay: false, logger: false, cross: false, customEvent: true }) const testContent = 'test-custom-event-dispatchEvent' emitter.$on(testContent, (event, expands, type) => { // test('应该正常获取 event, type', () => { // expect(type).toBe(testContent) // expect(event).toBe(testContent) // }) // test('[!] expands.customEvent === undefined', () => { // expect(expands.customEvent).toBe(undefined) // }) // // test('[*] expands.fromCustomEvent === true', () => { // expect(expands.fromCustomEvent).toBe(true) // }) }) window.dispatchEvent( new CustomEvent(realEventName, { detail: { type: testContent, event: testContent, expands: {} } }) ) emitter.$off(testContent) ``` ## 应用场景记录 | 版本 | 日期 | 说明 | | ---- | ------- |--| | v1 | 2023-11 | 用于登录弹窗 |