在 inject 时设置默认值可防止因祖先组件未 provide 而导致子组件访问 undefined 报错;需传入注入名和默认值,推荐用工厂函数避免副作用,并结合 TypeScript 泛型与 Symbol 键名统一保障类型安全与运行时健壮性。

在 inject 时设置默认值,是防止祖先组件没调用 provide 导致子组件拿到 undefined、进而触发运行时错误(比如访问 .value 或调用方法时报错)的关键做法。
inject 默认值的基本写法
inject 接收两个参数:注入名(字符串或 Symbol)和默认值。只要提供第二个参数,即使上层完全没 provide,也不会报错,而是直接返回该默认值:
-
const message = inject('message', '默认问候')→ 返回字符串 -
const user = inject('user', { name: '游客', id: 0 })→ 返回对象 -
const theme = inject('theme', ref('light'))→ 返回 ref,保持响应性一致
用工厂函数避免副作用
如果默认值需要计算(比如创建新对象、发起请求、初始化类实例),应使用函数形式传入,确保只在真正需要时才执行:
- ❌ 错误:直接传对象
inject('api', createApiClient())—— 每次 setup 都会新建实例 - ✅ 正确:
inject('api', () => createApiClient())—— 只在未提供时才调用 - 常见场景:默认返回空 ref、空 reactive、空数组或 null 函数
配合类型安全(TypeScript)更稳妥
在 script setup 中结合泛型和默认值,能同时保障类型推导和运行时安全:
const count = inject<Ref<number>>('count', ref(0))-
const store = inject<Store>('store', {} as Store)(推荐用工厂函数替代as Store) - 类型标注 + 默认值,让 IDE 和编译器都能提前发现潜在问题
Symbol 键名下也要设默认值
用 Symbol 作为注入名虽可避免命名冲突,但不改变 inject 的行为逻辑——仍需显式设默认值:
const myKey = Symbol('myService')const service = inject(myKey, { init() {}, destroy() {} })- 即使键唯一,也不能假设它一定被 provide;默认值仍是防御性编码的必要一环

















