第 24 题:Vue3 的组件通信方式(props / emit / v-model / provide-inject / expose / eventBus

第 24 题:Vue3 的组件通信方式(props / emit / v-model / provide-inject / expose / eventBus / store)


🎯 一、Vue3 组件通信方式总结表(可背)

通信方式 方向 适用场景 是否响应式
props 父 → 子 传值、配置
emit 子 → 父 通知事件、返回数据 N/A(事件)
v-model 双向(父 ↔ 子) 表单 / 双向绑定组件
provide / inject 祖先 → 后代 跨层级通信、通用组件 默认非响应式(可用 ref)
expose 子 → 父(实例 API) 暴露内部方法供父调用 N/A
EventBus 任意 ↔ 任意 小型项目的全局事件 依赖实现
Pinia / Vuex 全局共享 大型项目、复杂业务 ✅ 强响应式

🎯 二、各通信方式详解


1️⃣ Props:父 → 子(最核心通信方式)

示例

ini 复制代码
<Child :msg="parentMsg" />

子组件

scss 复制代码
defineProps({
  msg: String
})

适用场景

  • 父组件传值给子组件
  • 表单项、配置项、初始化数据

原理

编译模板时,props 变成组件的属性,最终映射到组件实例上。

Vue3 对 props 做 shallowReadonly,防止子组件修改。


2️⃣ Emit:子 → 父

子组件:

scss 复制代码
const emit = defineEmits(['update'])
emit('update', newVal)

父组件:

ini 复制代码
<Child @update="handleUpdate" />

适合:事件通知、按钮点击回调等。


3️⃣ v-model(双向通信)

Vue3 支持多个 v-model:

父:

ini 复制代码
<Child v-model:title="name" />

子:

ini 复制代码
const props = defineProps(['title'])
const emit = defineEmits(['update:title'])

emit('update:title', newVal)

本质:props + emit 的语法糖


4️⃣ provide / inject(跨层级通信)

祖先组件:

csharp 复制代码
provide('theme', ref('dark'))

后代组件:

ini 复制代码
const theme = inject('theme')

特点

  • 跨层级通信(不用 props 逐层传递)
  • 默认非响应式,如需响应式必须提供 ref/reactive

原理(常考)

provide 在组件创建时写入 "依赖注入表",

inject 在后代组件创建时从原型链查找依赖。


5️⃣ expose(子组件暴露方法给父组件)

Vue3 新增的,非常常用!

子组件:

scss 复制代码
const count = ref(0)
function reset() {
  count.value = 0
}

defineExpose({
  reset
})

父组件:

ini 复制代码
<Child ref="childRef" />

childRef.value.reset()

适用:表单校验、重置、打开弹窗等。

Vue3 默认 setup 中的方法不会暴露给父组件,必须用 expose。


6️⃣ EventBus(小项目用,全局事件通信)

Vue3 没有直接提供,可以自己用 mitt:

javascript 复制代码
import mitt from 'mitt'
export const bus = mitt()
csharp 复制代码
bus.emit('login', user)
bus.on('login', handler)

适合:

  • 非父子组件通信
  • 简单的全局事件系统

7️⃣ Pinia(全局状态管理)

ini 复制代码
const store = useUserStore()
store.name = 'jack'

最适合:

  • 大型项目
  • 全局共享数据
  • 多组件同步更新

Vue3 官方推荐 Pinia 代替 Vuex。


🎯 三、面试官常问对比题(高频)


❓ 1:provide/inject 与 props 的区别?

面试最佳答案:

  • props 是父 → 子单层传递,适合常规通信
  • provide/inject 是跨层级传递,不用每层都写 props
  • provide 默认非响应式,需要 ref 才能响应式
  • props 是强约束(类型校验),inject 是弱约束(不保证存在)

❓ 2:v-model 原理是什么?

答:

Vue3 中 v-model 等价于 modelValue + update:modelValue

本质仍然是父传值、子触发更新事件。


❓ 3:expose 为什么需要?

因为:

  • Vue3 的 setup 隔离作用域,默认不会暴露内部实例方法
  • 使用 expose 可以决定哪些方法安全地开放给外部

❓ 4:为什么要用 store(Pinia)?不能用 eventBus 吗?

简答:

  • eventBus 是事件驱动,不适合作状态管理
  • Pinia 是响应式数据管理,有 devtools、有模块化、有持久化
  • 大项目必须用 store

❓ 5:provide / inject 为什么默认不是响应式?

因为当初设计它用于"静态配置"(比如主题),要避免不必要更新;

若需要响应式,需要传 ref 或 reactive:

less 复制代码
provide('theme', reactive({ mode: 'dark' }))

🎯 四、一句话总结

Vue3 的通信体系基于 props/emit 构建,

provide/inject 解决跨层级传递,

expose 解决实例暴露,

store 解决全局共享,

eventBus 解决简单事件分发。

掌握这些,你能应对所有组件通信场景。

相关推荐
前端一课1 小时前
【vue高频面试题】第 21 题:Vue3 中的 Slot(插槽)— 基础、原理、使用场景、面试必问点
前端·面试
前端一课1 小时前
第 22 题:Teleport 的作用、原理和使用场景
前端·面试
前端一课1 小时前
第 29 题:Vue3 的 Teleport 原理(跨层级 DOM 挂载技术)
前端·面试
前端一课1 小时前
第 31 题:Vue3 中 watchEffect 的原理(依赖自动追踪 + 清理机制 + ReactiveEffect 全流程)
前端·面试
前端一课1 小时前
第 256 题:Vue3 的异步组件(defineAsyncComponent)+ Suspense 原理与面试高频点
前端·面试
前端一课1 小时前
第 27 题:Vue3 + TS 类型推断(Props 类型推导、Emit 类型推导、Setup 返回值类型)
前端·面试
是罐装可乐1 小时前
前端架构知识体系:通过发布-订阅者模式解耦路由和请求
前端·架构·vue·路由
杀死那个蝈坦1 小时前
监听 Canal
java·前端·eclipse·kotlin·bootstrap·html·lua
普贤莲花1 小时前
小米面试总结20251202
面试·职场和发展