Vue 组件通信方式

1. 面试题

Q: Vue 组件通信有哪些方式?父子、兄弟、跨层级组件如何传递数据?

2. 核心解答

Vue 提供了多种多样的通信机制,适应不同场景。

(1) 父子通信

  • Props:最基础的方式。父组件通过 props 向子组件传递数据。
    • 注意:单向数据流。子组件严禁修改 prop。
  • 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 拿到后,修改源对象不会触发视图更新。 解决:必须传递 refreactive 对象。 provide('config', ref({ theme: 'dark' }))

3. 总结

  • 父子: Props / Emit / v-model / Expose.
  • 兄弟: Pinia / Mitt.
  • 跨层级: Provide ~ Inject.