Vue事件传递实现原理
Vue 事件传递的实现原理
Vue 的事件传递主要通过 $emit 和 $on 方法实现,基于发布-订阅模式。子组件通过 $emit 触发事件,父组件通过 v-on 或 @ 监听事件,从而实现父子组件间的通信。
核心机制
-
$emit触发事件
子组件调用this.$emit(eventName, ...args)触发自定义事件。eventName是事件名称,args是传递给父组件的参数。 -
$on监听事件
父组件通过v-on:eventName="handler"或@eventName="handler"监听子组件触发的事件。handler是父组件中定义的回调函数。 -
事件中心(Event Bus)
跨组件通信时,可以创建一个空的 Vue 实例作为事件中心:const eventBus = new Vue(); // 组件A发送事件 eventBus.$emit('event-name', data); // 组件B监听事件 eventBus.$on('event-name', (data) => {});
源码解析
Vue 的事件系统在 src/core/instance/events.js 中实现,核心逻辑如下:
-
事件注册
$on方法将回调函数存入_events对象,键为事件名,值为回调函数数组:Vue.prototype.$on = function (event, fn) { const vm = this; (vm._events[event] || (vm._events[event] = [])).push(fn); return vm; }; -
事件触发
$emit方法遍历_events中对应事件名的回调函数并执行:Vue.prototype.$emit = function (event) { const vm = this; let cbs = vm._events[event]; if (cbs) { const args = [...arguments].slice(1); for (let i = 0; i < cbs.length; i++) { cbs[i].apply(vm, args); } } return vm; };
注意事项
-
事件命名规范
推荐使用 kebab-case(如my-event),因为 HTML 属性大小写不敏感。 -
移除事件监听
通过$off移除事件监听,避免内存泄漏:// 移除特定事件的所有监听 this.$off('event-name'); // 移除特定回调 this.$off('event-name', callback); -
一次性监听
使用$once监听一次后自动移除:this.$once('event-name', callback);
总结
Vue 的事件传递基于发布-订阅模式,通过 $emit 和 $on 实现组件通信。源码中通过 _events 对象管理事件回调,适用于父子组件或任意组件间的消息传递。合理使用事件中心(Event Bus)可简化跨层级通信。







