生态
mitt
vue3 不再建议使用 EventBus 作为全局事件总栈,改为推荐 mitt.js 库。
mitt 不依赖任何库,体积仅有 200bytes。也不依赖 vue 实例,这使得它可以在任何地方使用。
快速开始
与 vue2 EvenBus 类似的使用方式
1 2 3
| import mitt from "mitt"; export default mitt();
|
使用方式
其使用方式与 EventEmitter 类似:
- all:事件列表,map 类型
- on:注册时间
- off:移除事件
- all.clear:清空事件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import mittBus from "./mittBus";
const mariHandle = data => console.log( data );
const commonHandle = ( event, data ) => console.log( event, data )
mittBus.on( "mari", mariHandle );
mittBus.on( "*", commonHandle );
mittBus.emit( "asuka", { auth: "author" } );
mittBus.off( "mari", mariHandle );
mittBus.off( "*", commonHandle );
mittBus.all.clear();
|
原理
本质是使用 map 以键值对的方式保存事件,并通过闭包长期保存不被释放。个人实现方式如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| export function mitt( all = new Map() ) { return { all, on( type, handler ) { const handlers = all.get( type ); if ( handlers ) { handlers.push( handler ); } else { all.set( type, [ handler ] ); } }, off( type, handler ) { const handlers = all.get( type ); if ( handlers ) { const index = handlers.indexOf( handler ); if ( index !== -1 ) { handlers.splice( index, 1 ); } } }, emit( type, data ) { const handlers = all.get( type ) || []; handlers.slice().map( handler => { handler( data ); } ); if ( type !== "*" ) { const common = all.get( "*" ) || []; common.slice().map( handler => { handler( type, data ); } ); } } } }
|
问题
vue3 + echart5 时报错
在 vue3 中使用 echart5 出现如下报错。
1
| Cannot read properties of undefined (reading ‘type‘)
|
这是深层响应 Proxy 应用到了整个 echart 实例导致的问题,即对 echart 实例使用了 ref
或 reactive
。
不仅仅会报错,这也是 echart 官方不建议的行为,这样会影响实例底层的运行,并且会极大的降低图表的展示性能,官方解释。
可以通过定义普通变量或使用 shallowRef
等浅层响应保存 echart 实例来解决这个问题。
1 2 3 4
| const chart = echart.init( dom );
const chartRef = shallowRef( null ); chartRef.value = echart.init( dom );
|