vue事件实现原理
Vue 事件实现原理
Vue 的事件系统基于发布-订阅模式,通过 $on、$emit 等方法实现组件间通信。其核心原理分为以下几个部分:
事件注册与存储
Vue 实例初始化时会在内部维护一个 _events 对象,用于存储所有注册的事件及其对应的回调函数。例如:
vm._events = {
'click': [function handler1() {}, function handler2() {}],
'custom-event': [function handler() {}]
}
当调用 $on(event, callback) 时,Vue 会将回调函数添加到 _events[event] 的数组中。如果事件不存在,则创建一个新数组。
事件触发机制
调用 $emit(event, ...args) 时,Vue 会从 _events 中查找对应的事件名,并依次执行所有回调函数。伪代码如下:

Vue.prototype.$emit = function (event, ...args) {
const cbs = this._events[event]
if (cbs) {
cbs.forEach(cb => cb.apply(this, args))
}
}
原生 DOM 事件处理
对于模板中的 @click 等原生 DOM 事件,Vue 会通过以下步骤处理:
- 编译阶段:将模板中的
@click转换为v-on:click,并生成对应的渲染函数。 - 运行时:在
patch过程中,调用addEventListener绑定原生事件。 - 修饰符处理:
.stop、.prevent等修饰符会被转换为对应的原生事件操作。
自定义事件与组件通信
父子组件通过 v-on 和 $emit 实现通信:

<!-- 父组件 -->
<child @custom-event="handleEvent"></child>
<!-- 子组件 -->
<button @click="$emit('custom-event', data)">触发事件</button>
Vue 会在子组件触发事件时,通过父组件的 _events 查找并执行对应的回调函数。
事件解绑与销毁
调用 $off(event, callback) 会从 _events 中移除指定事件的回调函数。组件销毁时,Vue 会自动调用 $off 清理所有事件监听器。
核心源码分析
Vue 事件系统的核心逻辑位于 src/core/instance/events.js,关键实现如下:
// 事件注册
Vue.prototype.$on = function (event, fn) {
const vm = this
;(vm._events[event] || (vm._events[event] = [])).push(fn)
return vm
}
// 事件触发
Vue.prototype.$emit = function (event) {
const vm = this
let cbs = vm._events[event]
if (cbs) {
cbs = cbs.length > 1 ? toArray(cbs) : cbs
const args = toArray(arguments, 1)
for (let i = 0, l = cbs.length; i < l; i++) {
cbs[i].apply(vm, args)
}
}
return vm
}
性能优化点
- 事件缓存:高频触发的事件(如滚动)建议使用
_.throttle或_.debounce优化。 - 及时解绑:组件销毁前手动解绑全局事件(如
window.addEventListener)。 - 避免滥用:复杂场景优先考虑 Vuex 或 Provide/Inject 替代事件总线。
通过这种设计,Vue 实现了高效的事件系统,同时保持代码简洁性和可维护性。






