wot-design-uni useConfigProvider 组合式函数:在 JS 逻辑中注入全局主题配置的实战指南

原创2026-10-13 19:15:581,880 阅读
文章标签:UI组件移动开发小程序设计系统跨平台前端

wot-design-uni useConfigProvider 组合式函数:在 JS 逻辑中注入全局主题配置的实战指南

useConfigProvider 是 wot-design-uni 提供的一个组合式函数(Composable),用于在纯 JS 逻辑中注入全局配置(如主题变量),从而解决微信小程序等环境下组件渲染机制限制导致的 ConfigProvider 配置无法向下传递的问题。本文将从背景问题、基础用法、源码实现原理、类型系统、项目实战与测试验证六个层面,带你完整掌握该 API 的使用与底层机制。

一、为什么需要 useConfigProvider:依赖注入在小程序端的天然限制

在 Web 端,ConfigProvider 组件通过 Vue 的依赖注入(provide/inject)机制向下传递主题配置,子组件可以轻松获取父级配置。但在微信小程序等环境中,存在两类典型场景会导致这种传递失效:

  1. 原生插槽作用域隔离:小程序端组件渲染机制与 Web 不同,渲染在原生插槽中的节点可能无法访问插槽出口外层 ConfigProvider 组件的注入上下文,导致深度嵌套或跨组件树的组件拿不到父级主题配置。
  2. root-portal 节点搬移:使用 wd-root-portal 将节点渲染到根节点(如 H5 端的 teleport、小程序端的 root-portal、App 端的 renderjs)后,节点脱离了原有的组件树,注入上下文随之丢失。

正如 ConfigProvider 全局配置 文档所述,useConfigProvider 的核心价值在于:允许开发者直接在 JS 逻辑中注入配置,确保深层嵌套或跨组件树的组件也能正确获取主题样式。它需要与 ConfigProvider 组件配合使用——先用 ConfigProvider 组件包裹你的组件,再在逻辑层调用 useConfigProvider。

二、基础用法:reactive 与 ref 两种注入方式

useConfigProvider 接收一个包含 themeVars 的对象参数,themeVars 既可以是普通响应式对象(reactive),也可以是 ref 包装的响应式引用:

import { useConfigProvider } from '@/uni_modules/wot-design-uni'
import { reactive, ref } from 'vue'

// 使用 reactive
const themeVars = reactive({
  colorTheme: 'red',
  buttonPrimaryBgColor: '#07c160'
})

useConfigProvider({ themeVars })

// 或者使用 ref
const themeVarsRef = ref({
  colorTheme: 'blue'
})

useConfigProvider({ themeVars: themeVarsRef })

两种方式均支持响应式更新:当你后续修改 themeVars 或 themeVarsRef.value 中的属性值时,注入的主题样式会自动重新计算并同步到下游组件。

三、源码实现原理:provide/inject + CSS 变量映射

useConfigProvider 的实现位于 useConfigProvider.ts,整体逻辑非常精简,核心包含三部分:

1. 注入 Key 的定义

export const USE_CONFIG_PROVIDER_KEY = '__CONFIG_PROVIDER__'

该 Key 是组件与组合式函数之间通信的桥梁。wd-config-provider 与 wd-root-portal 组件内部都会通过 inject(USE_CONFIG_PROVIDER_KEY, None) 消费这份注入:

  • wd-config-provider.vue 在 themeStyle 计算属性中优先读取 hooksProvider.themeStyle.value,仅在未注入时回退到自身 props.themeVars;
  • wd-root-portal.vue 同样优先读取注入的 themeStyle,再回退到父级 ConfigProvider 的配置。

这意味着,只要你在逻辑层调用了 useConfigProvider,包裹在这些组件之下的所有 Wot 组件都能拿到你注入的主题变量,无需依赖组件树中的注入链。

2. 主题变量到 CSS 变量的映射

export const kebabCase = (str: string): string => {
  str = str.replace(str.charAt(0), str.charAt(0).toLocaleLowerCase())
  return str.replace(/([a-z])([A-Z])/g, (_, p1, p2) => p1 + '-' + p2.toLowerCase())
}

export const mapThemeVarsToCSSVars = (themeVars: Record<string, string>) => {
  if (!themeVars) return
  const cssVars: Record<string, string> = {}
  Object.keys(themeVars).forEach((key) => {
    cssVars[`--wot-${kebabCase(key)}`] = themeVars[key]
  })
  return cssVars
}

mapThemeVarsToCSSVars 的映射规则非常直观:

  • 将驼峰命名的变量名转成 kebab-case(短横线命名),并统一加上 --wot- 前缀;
  • 例如文档中的 colorTheme 会转换为 --wot-color-theme,buttonPrimaryBgColor 会转换为 --wot-button-primary-bg-color。

这正是 wot-design-uni 全部组件样式所依赖的 CSS 变量体系,与 ConfigProvider 主题定制 中"在 :root / page 节点上覆写 --wot-* 变量"的机制完全同源。

3. 注入响应式主题样式

export function useConfigProvider({ themeVars }: { themeVars: ConfigProviderThemeVars | Ref<ConfigProviderThemeVars> }) {
  const themeStyle = computed(() => {
    const styleObj = mapThemeVarsToCSSVars(unref(themeVars))
    return styleObj ? `${objToStyle(styleObj)}` : ''
  })

  provide(USE_CONFIG_PROVIDER_KEY, {
    themeStyle
  })
}

实现要点:

  • 通过 unref(themeVars) 统一解包 reactive 对象与 ref 引用,因此两种传参方式行为一致;
  • 用 computed 包裹,保证主题变量变化时样式字符串自动更新;
  • 最终通过 objToStyle(位于 common/util.ts)将 { '--wot-color-theme': 'red' } 形式的样式对象序列化为 --wot-color-theme:red; 这样的内联样式字符串,注入给下游组件使用。

四、类型系统:ConfigProviderThemeVars 全量主题变量

useConfigProvider 的参数类型为 ConfigProviderThemeVars | Ref<ConfigProviderThemeVars>。该类型定义在 types.ts,由 baseThemeVars 与数十个组件级主题变量类型交叉合并而成,覆盖了组件库中几乎全部组件。

1. 基础主题变量(baseThemeVars)

baseThemeVars 定义了一套全局基础色板与排版变量,例如:

变量 说明
colorTheme 主题色
colorSuccess / colorWarning / colorDanger 成功 / 警告 / 危险色
colorBg 背景色、禁用填充色
darkBackground ~ darkBackground7 深色模式下的多级背景色
colorTitle / colorContent / colorSecondary / colorAid 标题 / 正文 / 次要 / 辅助文字色
fsBig ~ fsAid 大型标题到辅助文字的字号
fwMedium / fwSemibold 字重 500 / 600
sizeSidePadding 屏幕两边留白 padding

2. 组件级主题变量

类型系统为每个组件提供了专属的变量分组,例如:

  • buttonThemeVars:buttonPrimaryBgColor、buttonPrimaryColor、buttonSmallHeight、buttonMediumRadius 等(types.ts);
  • cellThemeVars:cellPadding、cellTitleFs、cellLabelColor 等;
  • inputThemeVars、tabsThemeVars、toastThemeVars、navbarThemeVars 等数十个分组。

因此,在 TypeScript 项目中定义 themeVars 时,建议直接使用导出的 ConfigProviderThemeVars 类型以获得完整的类型提示:

import type { ConfigProviderThemeVars } from '@/uni_modules/wot-design-uni'

const themeVars: ConfigProviderThemeVars = {
  colorTheme: 'red',
  buttonPrimaryBgColor: '#07c160'
}

该类型已通过 index.ts 从组件库入口导出。

五、项目实战:page-wraper 中的动态主题注入

在本仓库的示例应用里,useConfigProvider 被真实用于页面包装组件。参见 page-wraper.vue:

const themeVars = computed<ConfigProviderThemeVars>(() => {
  return isRed.value ? { colorTheme: 'red' } : {}
})

useConfigProvider({ themeVars })

这是一个非常有代表性的实践模式:

  • 将 themeVars 声明为 computed<ConfigProviderThemeVars>,根据页面状态(如某个"红色主题"开关 isRed)动态返回不同的主题变量;
  • 直接调用 useConfigProvider({ themeVars }) 注入;
  • 当 isRed 状态变化时,注入的 --wot-color-theme CSS 变量随之更新,页面内所有 Wot 组件的主题色同步切换。

这种"逻辑层驱动主题"的写法,配合 wd-config-provider 组件的 theme 属性(light / dark 深色模式切换),可以组合出灵活的全局主题方案:组件树负责结构渲染,useConfigProvider 负责在任意 JS 位置注入样式配置,两者各司其职。

六、测试验证:三种传参方式的响应式行为

仓库的单元测试 useConfigProvider.test.ts 使用 vitest + @vue/test-utils 对组合式函数的行为做了完整验证:

  1. 普通对象:useConfigProvider({ themeVars: { colorTheme: 'red' } }) 后,子组件通过 inject(USE_CONFIG_PROVIDER_KEY) 能读取到 --wot-color-theme:red 样式字符串;
  2. reactive 对象:修改 themeVars.colorTheme = 'blue' 并 await nextTick() 后,注入的样式同步变为 --wot-color-theme:blue,验证了响应式更新链路;
  3. ref 引用:整体替换 themeVars.value = { colorTheme: 'green' } 后,样式同样更新为绿色。

这三条用例从测试层面印证了 computed + unref 实现同时兼容"属性级更新"与"引用级替换"两类响应式变更场景,为生产使用提供了可靠性保障。

七、API 参数说明

参数 说明 类型 默认值 最低版本
themeVars 主题变量对象,支持响应式更新 ConfigProviderThemeVars | Ref<ConfigProviderThemeVars> - 1.14.0

注意:该 API 自 1.14.0 版本引入,使用时请确认组件库版本不低于此版本。

八、使用建议与注意事项

  • 必须与 ConfigProvider 组件配合:useConfigProvider 注入的样式需要由 wd-config-provider 组件消费并应用到其子树,因此请确保你的组件被 ConfigProvider 包裹;
  • 优先在页面 / 应用顶层调用:注入是就近生效的,将 useConfigProvider 放在页面根组件或 App.ku.vue(配合虚拟根组件实现全局共享)等顶层位置,能最大化覆盖范围;
  • 善用 computed 实现动态主题:像 page-wraper 一样用 computed<ConfigProviderThemeVars> 返回主题变量,即可实现运行时主题切换;
  • 类型安全:使用 ConfigProviderThemeVars 类型约束 themeVars,既能获得智能提示,也能避免拼写错误的变量名导致 CSS 变量失效;
  • 变量命名遵循驼峰:主题变量统一使用驼峰命名(如 buttonPrimaryBgColor),内部会自动映射为 --wot- 前缀的 kebab-case CSS 变量,不要直接写 --wot-button-primary-bg-color 形式。

通过 useConfigProvider,你可以在微信小程序、H5、App 等所有端上,以统一、可靠的方式将全局主题配置注入到任意层级的组件中,彻底绕开小程序端依赖注入与原生插槽隔离带来的上下文丢失问题。

登录后查看全文
wot-design-uni