一聚教程网:一个值得你收藏的教程网站

热门教程

Vue 依赖注入如何在组合式函数中编写通用的依赖获取与校验逻辑

时间:2026-08-17 12:58:49 编辑:袖梨 来源:一聚教程网

组合式函数中应封装 inject 逻辑为 useInject,支持泛型、默认值、必填校验及环境差异化处理;配合 Symbol 键保障类型安全;按需扩展响应式访问器或插件级校验。

在组合式函数中封装依赖注入的获取与校验逻辑,核心是把 inject 调用、类型检查、默认值处理、缺失提示等统一抽象,避免每个组件重复写 const xxx = inject('key') 和防御性判断。

定义带类型和校验的 inject 工具函数

创建一个可复用的 useInject 组合式函数,接收 key、默认值、是否必填等参数:

  1. 用泛型约束返回值类型,配合 TypeScript 提升安全性
  2. 当未提供依赖且无默认值时,抛出明确错误(开发环境)或返回 undefined(生产环境)
  3. 支持传入工厂函数生成默认值,避免默认值被提前执行

示例代码:

import { inject, getCurrentInstance } from 'vue'export function useInject<T>(key: string | symbol,defaultValue?: T | (() => T),options: { required?: boolean; warnOnMissing?: boolean } = {}) {const instance = getCurrentInstance()const isProd = import.meta.env.PROD// 先尝试 injectlet value = inject<T>(key, undefined as any)// 若未注入且有默认值,按需解析if (value === undefined && defaultValue !== undefined) {value = typeof defaultValue === 'function' ? (defaultValue as Function)() : defaultValue}// 若仍为 undefined,按 required 策略处理if (value === undefined) {if (options.required) {const msg = `Missing required injection '${String(key)}'`if (isProd) {console.warn(msg)} else {throw new Error(msg)}}if (options.warnOnMissing && !isProd) {console.warn(`Injection '${String(key)}' not provided. Using fallback or undefined.`)}}return value}

配合 Symbol 做类型安全的 key 管理

避免字符串 key 拼写错误或冲突,建议将所有注入名集中定义为 Symbol:

  1. injections.ts 中统一导出 Symbol 键
  2. provide 侧和 inject 侧都引用同一 Symbol,TypeScript 可自动推导类型
  3. 组合式函数中直接使用 Symbol,无需字符串字面量

例如:

// injections.tsexport const ThemeSymbol = Symbol('theme')export const ApiClientSymbol = Symbol('api-client')// 在 provide 侧(如父组件或插件)import { ThemeSymbol } from './injections'provide(ThemeSymbol, reactive({ mode: 'light' }))// 在组合式函数中import { ThemeSymbol } from './injections'const theme = useInject(ThemeSymbol, { mode: 'dark' }, { required: true })

封装带响应式联动的依赖访问器

某些场景下,不仅需要读取注入值,还需触发更新或监听变化(比如主题切换后刷新 UI),可进一步封装:

  1. 返回一个包含 valueupdate 方法的对象(若提供者暴露了修改函数)
  2. 或返回一个计算属性 computed(() => ...),自动追踪注入的 ref 或 reactive
  3. 内部做空值 guard,防止因注入未就绪导致的运行时错误

示例:

import { inject, computed, Ref } from 'vue'import { ThemeSymbol } from './injections'export function useTheme() {const theme = inject<Ref<{ mode: string }>>(ThemeSymbol)if (!theme) {console.warn('Theme injection not available')return {mode: computed(() => 'light'),setMode: () => {}}}return {mode: computed(() => theme.value.mode),setMode: (mode: string) => { theme.value.mode = mode }}}

在插件或应用层统一注册并校验

对于全局 app.provide() 注入的依赖(如 i18n、router、auth),可在插件安装时预设校验规则:

  1. 插件内调用 app.config.globalProperties.$xxxapp.provide 同时注册元信息
  2. 组合式函数首次调用时,检查该 key 是否已在应用级注册(可通过 app._context.provides 粗略判断,但不推荐直接访问私有属性)
  3. 更稳妥方式:插件暴露一个 hasInjection(key) 工具供组合式函数调用

实际项目中,多数情况只需聚焦前三个方案——类型化 Symbol + 带默认值/报错策略的 useInject + 场景化访问器,就能覆盖 90% 的通用需求。

热门栏目