Vue 组件通信方式
1. 面试题
Q: Vue 组件通信有哪些方式?父子、兄弟、跨层级组件如何传递数据?
2. 核心解答
Vue 提供了多种多样的通信机制,适应不同场景。
(1) 父子通信
- Props:最基础的方式。父组件通过
props 向子组件传递数据。
- Emit:子组件通过
$emit 触发事件,父组件监听该事件。
- Expose / Ref:
- Vue 3 使用
defineExpose 暴露特定的属性或方法。
- 父组件通过
ref 访问子组件实例调用方法。
- v-model:双向绑定的语法糖,本质是 props + emit。
(2) 兄弟通信
- Mitt (EventBus):
- Vue 3 移除了
$on, $off,官方推荐使用 mitt 等第三方库实现事件总线。
- 场景:简单的跨组件通知。
- 状态管理 (Pinia/Vuex):
- 将共享状态放到 Store 中。
- 场景:兄弟组件共享数据(最正规的方式)。
- 父组件中转:
- 兄弟 A -> Emit -> 父组件 -> Props -> 兄弟 B。
(3) 跨层级通信
- Provide / Inject (依赖注入):
- 祖先组件
provide,后代组件 inject。
- 优点:避免 Props 透传 (Prop Drilling)。
- 场景:插件开发、UI 组件库(如 Form 到 FormItem)。
- Attrs:
v-bind="$attrs" 将父组件传递下来的未声明 Props,一次性透传给孙子组件。
(4) 常见问题
Q: Provide/Inject 是响应式的吗?
如果 provide 的值是一个普通对象 { name: 'foo' },它不是响应式的。通过 inject 拿到后,修改源对象不会触发视图更新。
解决:必须传递 ref 或 reactive 对象。
provide('config', ref({ theme: 'dark' }))。
3. 总结
- 父子: Props / Emit / v-model / Expose.
- 兄弟: Pinia / Mitt.
- 跨层级: Provide ~ Inject.