【vue高频面试题】第5题:Vue3 的父子组件通信方式有哪些?分别适用于什么场景?

Vue3 高频题 · 第 5 题

主问题

问:Vue3 的父子组件通信方式有哪些?分别适用于什么场景?


一、面试官期望你说出的目录(总览)

Vue3 父子通信主要包括:

父 → 子

  1. props(最常用)
  2. defineProps(script setup)
  3. v-model(子组件双向绑定)
  4. provide / inject(跨层级)

子 → 父

  1. emit(自定义事件)

双向 & 深层 / 全局

  1. v-model 修饰事件 + 多 v-model
  2. provide / inject(跨层级)
  3. 全局 store(Pinia)
  4. 模板引用 ref + defineExpose(父直接调用子方法)

二、核心回答(逐一解释 + 场景)

1)props:父 → 子(最标准方式)

父组件传值给子组件。

xml 复制代码
<!-- parent -->
<Child :title="msg" />

<!-- child -->
<script setup>
const props = defineProps({
  title: String
})
</script>

适用场景

  • 结构简单
  • 仅需单向数据流

2)emit:子 → 父

子组件触发事件,让父组件接收。

xml 复制代码
<!-- child -->
<script setup>
const emit = defineEmits(['update'])
emit('update', 123)
</script>

<!-- parent -->
<Child @update="getVal" />

适用场景

  • 子组件需要通知父组件:点击、选择、提交等。

3)v-model:父 ↔ 子 双向绑定

Vue3 扩展了 v-model,可以多字段。

xml 复制代码
<!-- parent -->
<Child v-model="username" />

<!-- child -->
<script setup>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
</script>

适用场景

  • 输入类组件(input/select)
  • 封装表单组件

4)多 v-model

xml 复制代码
<!-- parent -->
<Child v-model:first-name="first" v-model:last-name="last" />

<!-- child -->
defineProps(['firstName', 'lastName'])
defineEmits(['update:firstName', 'update:lastName'])

适合场景

  • 自定义表单组件,同时绑定多个字段

5)provide / inject(跨层级通信)

不需要一层层 props 传递。

arduino 复制代码
// parent
provide('theme', 'dark')

// child descendant
const theme = inject('theme')

适合场景

  • 组件跨层级传递全局信息:主题、配置、上下文数据
  • 常用于 UI 组件库(如 Element-Plus)

6)父 ref 调用子组件方法(defineExpose)

父组件直接访问子组件实例内部方法。

xml 复制代码
<!-- child -->
<script setup>
function validate() { ... }
defineExpose({ validate })
</script>
xml 复制代码
<!-- parent -->
<Child ref="childRef" />
childRef.value.validate()

适用场景

  • 表单校验
  • 滚动控制
  • 模态框的 open/close

7)使用 Pinia / Vuex(全局状态)

父子、跨组件、兄弟全都能用。

适合场景

  • 全局共享状态:用户信息、设置、token
  • 复杂项目

三、深度追问(面试官常用)

(1)props 为什么是单向数据流?能不能改?

不能! Vue 禁止子组件直接修改 props。

因为会导致状态来源混乱,难以维护。

如果需要修改:

  • 用 emit 通知父组件
  • 或者在子组件内部复制一份:
csharp 复制代码
const localVal = ref(props.value)

(2)provide 的数据是响应式吗?

默认 不是响应式的

需要响应式需要这样:

less 复制代码
provide('user', reactive({...}))
provide('count', ref(0))

inject 自动保持响应式。


(3)为什么某些组件库大量使用 provide/inject?

因为组件层级深(例如 Menu / Form / Table)

props 传递太麻烦

provide/inject 结构更清晰


(4)父组件 ref 调用子方法有什么风险?

  • 父对子产生强耦合
  • 组件难复用
  • 必须等待子组件挂载后才能调用

四、面试官 killer 问题(加分项)

❓ "父组件能否监听子组件 props 的变化?"

答:不能直接监听,但可以:

  • 使用 watch(() => props.xxx) 在子组件监听 props
  • 或者在父组件监听自己的数据(推荐)

❓ "如果 provide 的数据是 reactive,对象属性新增会响应吗?"

会。因为 Proxy 拦截的是整个对象。


❓ "v-model 和 props + emit 比,有什么优点?"

  • 更统一的 API
  • 多字段 v-model
  • 更抽象,更适合封装组件

五、最终小结(可以背诵)

父传子用 props ,子传父用 emit

双向绑定用 v-model

跨层级用 provide/inject

父调子方法用 ref + defineExpose

复杂共享状态用 Pinia

相关推荐
崔庆才丨静觅6 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60617 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了7 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅7 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅8 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅8 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment8 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅8 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊8 小时前
jwt介绍
前端