Vue3组合式API改造:render组件监听子组件事件替代$on方案
Vue3组合式API替代$on监听事件方案
针对你需要将Vue2中使用$on监听事件的代码转换为Vue3组合式API的场景,这里提供两种可行方案:
方案一:自定义简易事件发射器(无需第三方库)
由于Vue3移除了组件实例的$on/$off方法,我们可以在组件内部实现一个轻量事件发射器替代:
import { ref, h } from 'vue'; export default { setup(props, { slots }) { // 响应式变量 const elementTop = ref(0); const elementHeight = ref(0); // 绑定组件根元素 const rootEl = ref(null); // 简易事件发射器 const eventBus = { events: {}, on(eventName, handler) { this.events[eventName] = this.events[eventName] || []; this.events[eventName].push(handler); }, emit(eventName, ...args) { this.events[eventName]?.forEach(handler => handler(...args)); } }; // 原updateElementBounds逻辑 const updateElementBounds = () => { if (rootEl.value) { const { offsetTop, offsetHeight } = rootEl.value; elementTop.value = offsetTop; elementHeight.value = offsetHeight; } }; // 绑定事件(替代原created中的$on) eventBus.on('update-visibility', updateElementBounds); // 若需内部触发事件,调用eventBus.emit('update-visibility')即可 // 渲染函数 return () => h('div', { ref: rootEl }, [ slots.default?.({ isPageFocused: props.isPageFocused, isElementFocused: props.isElementFocused }) ]); } };
方案二:使用mitt事件库
如果需要更完善的事件处理能力,可以引入mitt库:
- 安装mitt:
npm install mitt
- 组件代码:
import { ref, h } from 'vue'; import mitt from 'mitt'; export default { setup(props, { slots }) { const elementTop = ref(0); const elementHeight = ref(0); const rootEl = ref(null); // 创建mitt实例 const emitter = mitt(); const updateElementBounds = () => { if (rootEl.value) { const { offsetTop, offsetHeight } = rootEl.value; elementTop.value = offsetTop; elementHeight.value = offsetHeight; } }; // 绑定事件 emitter.on('update-visibility', updateElementBounds); // 内部触发事件示例:emitter.emit('update-visibility') // 渲染函数 return () => h('div', { ref: rootEl }, [ slots.default?.({ isPageFocused: props.isPageFocused, isElementFocused: props.isElementFocused }) ]); } };
补充说明
- 原代码中的
this.$el在Vue3中通过ref绑定根元素获取,确保能正确访问DOM节点。 - 若
update-visibility事件由插槽内的子组件触发,可直接在插槽参数中传递回调函数,让子组件调用:
子组件内通过// 渲染函数中修改slot参数 slots.default?.({ isPageFocused: props.isPageFocused, isElementFocused: props.isElementFocused, onUpdateVisibility: updateElementBounds // 传递回调给子组件 })props.onUpdateVisibility()触发即可,无需使用事件发射器。
内容的提问来源于stack exchange,提问作者EXayer
相关产品推荐
相关产品推荐

