Vue 组件通信有哪些方式?props、emit、provide/inject、Pinia 怎么选?
🧑💻 面试官:Vue 组件通信有哪些方式?
🙋♂️ 我:props、emit、provide/inject,还有 Pinia。
🧑💻 面试官:一棵树里深层按钮要调用表单校验,你会把它放 Pinia 吗?
🙋♂️ 我:层级太深,放全局 store 比较方便。
🧑💻 面试官:如果页面同时打开两份表单,全局校验对象属于哪一份?
组件通信先问数据属于谁、需要共享到哪里,再选传递方式;层级深不等于必须全局。
面试速答(60 秒版)
父组件向子组件传数据,优先用 props;子组件通知父组件发生了什么,使用 emit。组件事件不会像 DOM 事件一样沿祖先自动冒泡。
一组深层组件共享同一个上下文,例如表单、主题或组件库配置,可以用 provide/inject。它的范围由提供者决定,多个实例可以各有自己的上下文。
真正跨页面、跨组件长期共享的客户端状态,再考虑 Pinia。不要只因为传了几层 props,就把局部状态搬进全局 store。
选择时主要检查数据归属、共享范围、修改入口和生命周期。通信方式方便,不代表状态就管理得清楚。

知识点详解:通信方式要跟着状态范围走
父子之间,把输入和通知说清楚
假设商品列表拥有选中的商品 ID,商品卡片展示商品,并通知用户点击了哪一个。
商品数据通过 props 传给卡片;卡片 emit 一个选择事件;列表决定是否更新选中状态。子组件报告“用户选择了商品”,比直接调用父组件内部某个变量更容易维护。
组件事件只会交给直接监听它的父组件,不会自动传到祖父组件。多层需要明确转发,或者重新判断是否该用上下文。不能拿 DOM 冒泡的理解直接套到 emit 上。
这也解释了为什么事件名称最好描述发生的事,而不是暴露父组件当前怎么实现。
深层共享,不一定意味着全站共享
表单下有字段、布局、提示和按钮。深层按钮需要访问当前表单的校验能力,如果层层传入,接口会被这些中间组件占满。
provide/inject 可以让表单提供自己的上下文,后代按约定取用。页面同时显示两份表单时,后代拿到的是最近的提供者,各自管理自己的数据。
它不会凭空把普通值变成响应式;提供 ref 等响应式对象时,后代才能沿着这份响应式关系使用。修改入口也最好留在提供者,通过提供操作函数或只读数据约束后代。
TypeScript 项目可以使用 InjectionKey 约定类型,并处理“没有找到提供者”的情况。Python 没有对应的 Vue 组件注入运行时,本题不编造对等 API。
Pinia 管共享状态,不是替代所有组件关系
登录用户、跨页面草稿或多个组件共同操作的状态,可以集中放进 store。Pinia 让状态、派生值和操作有明确入口,调试和插件能力也能接进来。
但弹窗是否打开、单个输入框尚未确认的内容,常常只属于一个组件。把它们全部放进全局,容易留下关闭页面后还存在的旧状态。
服务端渲染还需要注意隔离:不同请求不能误用同一份用户状态。使用框架的 Pinia 集成,并按它的服务端规则创建、序列化和恢复状态,不要自己把所有用户都接到一个模块级单例上。
从接口请求来的数据,还要另外想好缓存、过期和重新获取;“放进 store”并没有自动回答这些问题。
选型时,用一张归属表比背清单有用
| 数据或能力 | 典型范围 | 首先考虑 |
|---|---|---|
| 商品卡片输入、点击通知 | 直接父子 | props / emit |
| 当前表单上下文 | 一个提供者的后代 | provide / inject |
| 跨页面共享的用户状态 | 应用范围 | Pinia |
| 单个编辑框草稿 | 当前组件 | 本地响应式状态 |
这张表不是强制规定。你可以根据项目调整,但必须解释状态为什么放在那里、由谁修改、何时清掉。
如果三种方案都能做,通常先选范围更小、依赖更明确的那一种,后面确实需要共享时再扩大。
本题机制参考:Vue:Component Events、Vue:Provide / Inject、Pinia:Introduction。
面试官继续追问
provide/inject 可以完全替代 Pinia 吗?
都能传递共享对象,但用途和配套不同。组件上下文强调提供者范围;应用级 store 还提供状态组织、调试和插件等能力。
emit 会像点击事件一样一直冒泡吗?
不会。Vue 组件事件需要父组件监听,跨层传递要显式处理。
全局状态越少越好吗?
不是越少越好,而是范围要合适。确实跨页面共享的数据不应复制到很多组件里各自维护。
面试速记卡
- props:父组件向子组件提供输入。
- emit:子组件报告事件,不自动跨祖先冒泡。
- provide/inject:按提供者范围共享深层上下文。
- Pinia:组织应用级共享状态,不承包所有局部状态。
- 判断顺序:归属、范围、修改入口、生命周期。
公司面试真题
真题根据求职者公开面经整理,题意经过概括,非逐字原话或公司官方题库;本文为 Sunday 的独立解析。
小米 · 前端 · 原帖未明确批次
Vue 父子组件怎样通信?(题意整理)
小米前端二面 ↗
原帖编辑于 2024-05-29腾讯 · 前端(TEG / QQ音乐 / PCG) · 暑期实习
Vue 父子、子父和隔代组件怎样传值?(题意整理)
腾讯暑期实习前端面经 + 总结 ↗
面试记录为 2020 年 3 月;原帖编辑于 2020-04-19