Sunday面试指南

Vue 组件通信有哪些方式?props、emit、provide/inject、Pinia 怎么选?

🧑‍💻 面试官:Vue 组件通信有哪些方式?

🙋‍♂️ 我:props、emit、provide/inject,还有 Pinia。

🧑‍💻 面试官:一棵树里深层按钮要调用表单校验,你会把它放 Pinia 吗?

🙋‍♂️ 我:层级太深,放全局 store 比较方便。

🧑‍💻 面试官:如果页面同时打开两份表单,全局校验对象属于哪一份?

组件通信先问数据属于谁、需要共享到哪里,再选传递方式;层级深不等于必须全局。

面试速答(60 秒版)

父组件向子组件传数据,优先用 props;子组件通知父组件发生了什么,使用 emit。组件事件不会像 DOM 事件一样沿祖先自动冒泡。

一组深层组件共享同一个上下文,例如表单、主题或组件库配置,可以用 provide/inject。它的范围由提供者决定,多个实例可以各有自己的上下文。

真正跨页面、跨组件长期共享的客户端状态,再考虑 Pinia。不要只因为传了几层 props,就把局部状态搬进全局 store。

选择时主要检查数据归属、共享范围、修改入口和生命周期。通信方式方便,不代表状态就管理得清楚。

props与emit用于父子通信,provide/inject用于局部上下文,Pinia用于跨页面共享

知识点详解:通信方式要跟着状态范围走

父子之间,把输入和通知说清楚

假设商品列表拥有选中的商品 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

浏览公司面试真题 →
简历汪永久免费在线制作简历,模板直接套用、导出无水印,永久免费、下载免费,不需要付费解锁任何功能。去写简历