Inject 只取祖先链中最近一层同名 provide 的值,无合并逻辑;应使用 Symbol 作为 key 避免冲突,并通过不同 key 分别注入再手动组合多源数据。

Inject 本身不支持“合并多个同名 key 的注入”,它只取最近一层 provide 的值。所谓“多个来源”,实际是祖先链上多个组件分别 provide 了相同 key,这时 inject 拿到的是离自己最近的那个 —— 后者会覆盖前者,没有合并逻辑。
同名 key 的覆盖行为是确定的
Vue 的 provide/inject 沿着组件树向上查找,一旦找到第一个匹配 key 的 provide,就停止搜索。这意味着:
- 祖父组件 provide('theme', 'light'),父亲组件也 provide('theme', 'dark'),子组件 inject('theme') → 得到 'dark'
- 即使祖父提供了响应式数据、父亲提供普通字符串,也不会自动降级或回退
- 没有警告、不报错、不提示冲突,覆盖静默发生
避免意外覆盖的实用做法
靠命名规范(比如加前缀)容易疏漏,尤其在大型项目或引入第三方库时。更可靠的方式是:
- 用 Symbol 定义注入 key:每个 Symbol 天然唯一,不同模块即使定义同名 Symbol 描述,也不相等
- 把 Symbol 提前导出为常量,供 provide 和 inject 两端统一导入使用,杜绝字符串拼写错误或重复
- 配合 TypeScript 的 InjectionKey
类型,让 IDE 能校验类型、防止 key 错配
需要真正“多源注入”?得手动设计结构
如果业务确实要组合多个祖先的数据(比如主题 + 权限 + 用户配置),不要依赖同名 key 注入,而是:
- 每个来源用不同 key 提供,例如
provide(themeKey, theme)、provide(authKey, auth) - 在接收组件中分别 inject,再在 setup 里组合成一个对象或 computed
- 或者封装一个组合式函数(composable),内部统一管理多个注入点并返回聚合后的状态
不复杂但容易忽略

















