【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

相关推荐
子兮曰20 小时前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰20 小时前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万21 小时前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝21 小时前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋21 小时前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
晨米酱1 天前
AGENTS.md:Agent 的上下文策略层
面试·架构·agent
卡布鲁1 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
彧azz1 天前
Linux 环境下 Redis 学习总结:数据类型、持久化、锁、事务、主从与缓存问题
linux·redis·笔记·学习·面试
汉堡大王95271 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大1 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端