Vue3组件通信 emit 的工作原理
文章目录
- 前言
- 🔧 使用方式简述
- ⚙️ 源码角度解析 `emit`
- 一、组件实例初始化时的 `emit`
- 二、emit 函数的定义
- 三、关键点说明
- 🧠 总结流程图(简化)
- 🔍 结合运行时举个实际例子
- 📌 总结
前言
Vue 3 中 emit
是组件之间通信的重要机制,通常用于 子组件向父组件发送事件。下面我们结合源码,深入理解 emit
的工作原理。
🔧 使用方式简述
子组件中:
defineProps(['msg'])
const emit = defineEmits(['change'])function triggerChange() {emit('change', 'new value')
}
父组件中:
<MyComponent @change="onChange" />
⚙️ 源码角度解析 emit
Vue 3 中的 emit
是在 组件实例 (ComponentInternalInstance
) 的上下文中定义的函数。它的实现主要在 Vue 3 的核心包 @vue/runtime-core
中。
一、组件实例初始化时的 emit
位于:packages/runtime-core/src/component.ts
export function createComponentInstance(...) {const instance: ComponentInternalInstance = {...emit: (...args) => {emit(instance, ...args)}}...
}
这里 emit
是一个闭包,它绑定了当前组件实例,最终调用了 emit(instance, ...args)
这个方法。
二、emit 函数的定义
位于:packages/runtime-core/src/componentEmits.ts
export function emit(instance: ComponentInternalInstance,event: string,...rawArgs: unknown[]
) {const props = instance.vnode.props || EMPTY_OBJlet handlerName = toHandlerKey(event) // 比如 'change' => 'onChange'let handler = props[handlerName]if (!handler && event.toLowerCase() !== event) {handler = props[handlerName.toLowerCase()]}if (handler) {callWithAsyncErrorHandling(handler, instance, ErrorCodes.COMPONENT_EVENT_HANDLER, args)}
}
三、关键点说明
步骤 | 内容 |
---|---|
toHandlerKey('change') | 会变成 onChange ,这是 Vue 事件绑定的内部规则 |
props.onChange | 从组件的 vnode.props 上查找对应的事件处理函数 |
callWithAsyncErrorHandling | 调用函数时,带有错误处理机制(防止 UI 崩溃) |
🧠 总结流程图(简化)
emit('change', value)↓
组件内部的 emit 实例函数↓
调用 @vue/runtime-core 的 emit(instance, 'change', value)↓
查找 props 中的 onChange↓
找到后执行 onChange(value)
🔍 结合运行时举个实际例子
const emit = defineEmits(['submit'])function onClick() {emit('submit', { name: 'Vue' })
}
编译后模板中,父组件绑定的是 onSubmit
:
<Child @submit="handleSubmit" />
Vue 会在创建 VNode 时把 @submit="handleSubmit"
转成:
props: {onSubmit: handleSubmit
}
然后通过上面提到的 emit
源码逻辑找到 onSubmit
并执行。
📌 总结
- Vue 3 中的
emit
是通过组件实例绑定的emit
函数实现的; - 实际调用的是
runtime-core
中的emit(instance, eventName, ...args)
; emit
会根据事件名(如change
)生成onChange
并在props
中查找是否有对应函数;callWithAsyncErrorHandling
确保事件处理函数执行时出错不会影响整个应用。