用Provide实现全局主题色需三要素:响应式ref状态、统一setTheme方法、CSS变量联动;inject时传默认ref值,watch监听自动更新样式。

用 Provide 实现全局主题色配置,关键不是把颜色值“塞进去”,而是让所有用到主题色的组件能实时感知变化、自动更新样式。核心在于响应式状态 + 正确注入 + CSS 变量联动,三者缺一不可。
用 ref 包裹主题状态,确保可变可响应
Provide 的值本身不会触发更新。如果直接 provide('theme', 'dark'),后续改值子组件完全无感。
- 正确做法:用 ref 创建主题状态,例如
const theme = ref('light'),再provide('theme', theme) - 子组件 inject 后拿到的是原始 ref,直接用
theme.value读写,watch 也能监听变化 - 避免传普通对象或字符串——它们没有响应性,无法驱动重渲染
统一暴露切换方法,封装逻辑不散落
不要让每个页面都手动改 theme.value = 'dark',容易遗漏、难维护、无法持久化。
- 在 provide 侧同时暴露状态和方法,例如:
provide('theme', { theme, setTheme: (val) => { theme.value = val; localStorage.setItem('theme', val); } }) - 切换时同步写入 localStorage,下次加载可自动恢复
- 可在 setTheme 内部加入事件通知、日志上报等扩展逻辑
用 CSS 变量解耦样式,动态映射主题色
纯 class 切换难以覆盖细粒度颜色,CSS 自定义属性才是现代主题方案的基石。
- 在根节点(
document.documentElement)上设置变量,例如:document.documentElement.style.setProperty('--primary-color', '#007bff') - 配合 watch 监听 theme 变化,自动更新变量值
- CSS 中统一使用
var(--primary-color),按钮、文字、边框等样式全部响应切换 - 支持渐变、阴影、过渡动画等复杂效果,无需重复写多套 class
子组件安全注入并响应更新
inject 不是万能钥匙,需注意默认值和使用方式,否则容易报错或丢失响应。
- 调用 inject 时建议传默认值,例如
const theme = inject('theme', ref('light')) - 模板中可直接写
{{ theme.value }}或:class="`theme-${theme.value}`" - 逻辑中 watch(theme, ...) 即可捕获变化,无需 toRef 或 unref 二次包装
- 兄弟组件若需同步,必须共有一个祖先 provider;Provide/Inject 不是全局总线










