真实面经题目 · 原创解析

Vue 父子组件有哪些通信方式?

Vue 父子组件通信最基础的是 props 向下传递数据、emit 向上传递事件;更复杂的场景还包括 v-model 双向约定、slot 和作用域插槽传递渲染能力、ref 与 defineExpose 暴露子组件方法、provide/inject 跨层传递依赖,以及通过 Pinia 或 Vuex 管理跨组件共享状态。

出现于:字节跳动 · 前端

60 秒回答模板

父子组件通信可以按数据方向回答。父到子用 props,子组件把数据声明为只读输入;子到父用 emit,父组件监听事件并决定如何更新状态。需要表单式双向绑定时,可以用 v-model,本质仍是 prop 加 update 事件的语法约定。父组件要调用子组件少量命令式能力时,可以通过 ref 获取子组件实例,Vue 3 中子组件需要 defineExpose 明确暴露。传递内容结构时用 slot,子组件要把内部数据交给父级定制渲染时用作用域插槽。跨多层组件可以用 provide/inject,但全局业务状态更适合 Pinia 或 Vuex。

考点 主线模式
难度 真实面经高频题
回答目标 讲清机制、边界和追问

深入解析

01

Props 向下

props 是父组件向子组件传递数据的主要方式。子组件声明自己需要哪些输入,父组件负责提供。这个方向符合单向数据流:父级拥有状态,子级根据输入渲染。子组件不应直接修改 prop,因为这会破坏数据来源的清晰性;如果需要修改,应通过 emit 通知父组件,或者在子组件内部创建本地副本并定义同步策略。

02

Emit 向上

子组件不能直接改变父组件内部状态,应该通过 emit 发送事件,把用户行为或内部状态变化告诉父级。父组件监听事件后决定是否更新数据、调用接口或触发其他副作用。这个模式让子组件保持可复用:它只表达发生了什么,而不关心父组件如何处理。Vue 3 中可以通过 defineEmits 明确声明事件,提升类型提示和可维护性。

03

v-model 约定

v-model 适合父子之间存在一个主要受控值的场景,例如输入框、选择器、弹窗开关。它不是神秘的双向数据绑定,而是一个约定:父组件传入 modelValue 或指定名称的 prop,子组件触发 update:modelValue 或对应 update 事件。Vue 3 支持多个 v-model,能让复杂组件把分页、筛选、开关等状态拆成明确的受控接口。

04

Slot 传结构

props 传数据,slot 传渲染结构。父组件可以通过插槽把按钮、列表项、空状态、头部区域等内容交给子组件放到特定位置。作用域插槽则让子组件把内部数据暴露给父组件,由父组件决定如何渲染。这在表格、列表、表单容器中很常见:容器组件负责逻辑和布局,父组件负责具体内容表达。

05

Ref 与依赖

ref 适合少量命令式通信,例如父组件调用子组件的 focus、validate、reset 方法。Vue 3 的 setup 组件默认不会把内部成员全部暴露给父级,需要通过 defineExpose 明确开放。provide/inject 适合祖先向深层后代传递上下文,例如表单上下文、主题、注册方法;但它会降低依赖显式程度,业务共享状态通常应放到 Pinia 或 Vuex。

易错点

  • 只回答 props 和 emit,遗漏 v-model、slot、ref、provide/inject 和状态管理等实际工程手段。
  • 把 v-model 说成真正任意双向同步,没有解释 prop 与 update 事件约定。
  • 滥用事件总线或 $parent 解决所有通信问题,导致组件边界不清晰。
  • 把 provide/inject 当作全局状态管理替代品,忽略它更适合组件树上下文依赖。

面试官追问

props 为什么不建议在子组件里直接修改?

props 的来源在父组件,子组件直接修改会让数据流变得不可追踪。父组件重新渲染时还可能覆盖子组件的修改。更好的方式是 emit 事件让父组件更新,或创建本地状态并明确同步规则。

v-model 在 Vue 3 中的本质是什么?

默认是 modelValue 这个 prop 加 update:modelValue 这个事件的组合。也可以使用具名 v-model,形成多个 prop 和 update 事件的受控接口。

provide/inject 和 Pinia 应该怎么选?

provide/inject 适合组件树上下文,尤其是同一组组件内部协作;Pinia 适合跨页面、跨模块的业务共享状态,需要调试、持久化、异步 action 或统一数据来源时更合适。

什么时候可以用 ref 调子组件方法?

当交互本身是命令式动作时可以使用,例如 focus、scrollTo、validate、reset。不要把大量业务数据同步建立在 ref 方法调用上,否则父子组件会高度耦合。