【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

相关推荐
Funny Valentine-js37 分钟前
web实验后端php测试文本
前端·javascript·php·html5·cookie·telnet·session
前端一课40 分钟前
【vue高频面试题】第6题:Vue3 中 Composition API 和 Options API 有什么区别?为什么 Composition API 更推荐
前端·面试
前端一课44 分钟前
【vue高频面试题】第7题:Vue3 中 `v-model` 的工作原理是什么?为什么 Vue3 支持多个 v-model?如何在子组件中实现?
前端·面试
luguocaoyuan44 分钟前
前端沙箱隔离技术详解:从原理到实践
前端
前端一课1 小时前
【vue高频面试题】第3题:Vue 3 中的 computed 是什么?和 watch 有什么区别?什么时候用哪一个?
前端·面试
Json____1 小时前
vue2-数码购物商城-前端静态网站
前端·vue·数码商城
@大迁世界1 小时前
03.CSS嵌套 (Nesting)
前端·css
DevUI团队1 小时前
解锁前端高阶调试:浏览器/IDE/Git技巧分享
前端·javascript·html
前端一课1 小时前
【vue高频面试题】第一题:Vue 3 相比 Vue 2,有哪些重大变化?
前端·面试