【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

相关推荐
lalala_Zou1 天前
小米日常实习一面
java·后端·面试
梦想是准点下班1 天前
【vue3】 + 【vite】 + 【vite-plugin-obfuscator】混淆打包 => 放弃了,样式会丢
前端·vue.js
前端达人1 天前
原生JavaScript vs 前端框架,2026年该怎么选?
开发语言·前端·javascript·前端框架·ecmascript
漫天黄叶远飞1 天前
React 组件通讯全攻略:拒绝 "Props" 焦虑,掌握数据流动的艺术
前端·react.js·前端框架
梦想是准点下班1 天前
【vue3】 + 【vite】 + 【rollup-plugin-obfuscator】混淆打包 => 打包报错
前端·vue.js
恋猫de小郭1 天前
Flutter UI 设计库解耦重构进度,官方解答未来如何适配
android·前端·flutter
星_离1 天前
高德地图-物流路线
前端·vue.js
细心细心再细心1 天前
Lexical 富文本编辑器组件详解
前端
qq_406176141 天前
JavaScript中的循环
前端
小皮虾1 天前
搞全栈还在纠结 POST、GET、RESTful?试试这个,像调用本地函数一样写接口
前端·node.js·全栈