provide/inject 本身不自动创建响应式,关键在于传入 ref 或 reactive 包裹的值;推荐用 symbol 作 key 避免冲突;方法和状态宜封装后统一 provide;inject 默认值需用 ref 才响应。

Provide / Inject 本身不自动创建响应式,它只是“传递引用”。真正让跨层级共享保持响应式的,关键在于你传进去的是不是响应式对象——不是字符串、普通对象或函数本身,而是 ref 或 reactive 包裹后的值。
必须用 ref 或 reactive 包裹数据
如果你直接 provide 一个普通字符串或对象,后代组件 inject 后修改它,视图不会更新:
- ❌ 错误写法:
provide('theme', 'dark')—— 字符串非响应式,改了也不触发重渲染 - ✅ 正确写法:
provide('theme', ref('dark'))或provide('theme', reactive({ mode: 'dark' })) - 注入后,后代组件可直接读写
theme.value(ref)或theme.mode(reactive),变化实时同步
推荐用 Symbol 作 key 避免冲突
字符串 key 容易被其他组件意外覆盖,尤其在大型项目或 UI 库中:
- 定义统一 key:
const themeKey = Symbol('theme'),放在独立文件中导出复用 - 祖先组件:
provide(themeKey, ref('light')) - 后代组件:
const theme = inject(themeKey),类型安全且无命名污染
方法和状态一起提供更实用
光传数据不够,往往还要传修改逻辑。把 ref 和函数一起封装进对象再 provide,结构清晰又响应:
const color = ref('blue')provide(themeKey, { color, setColor: (c) => color.value = c })- 后代组件解构使用:
const { color, setColor } = inject(themeKey),模板中直接{{ color }},点击调用setColor('red')
注意默认值的响应式陷阱
inject 支持设默认值,但默认值本身不参与响应式系统:
-
inject('theme', 'light')→ 返回字符串,改了无效 - 如需默认值也响应,应写成:
inject('theme', ref('light')),再手动判断是否为 undefined - 更稳妥做法:只在 provide 侧确保必传,inject 侧不做默认值依赖











