provide/inject 是 vue 跨层级共享响应式主题配置的轻量方案:用 ref/reactive 创建主题状态并 provide,子组件 inject 后直接通过 .value 读写并自动响应更新,配合 watch 切换 css 变量实现样式动态适配。

Provide/Inject 是 Vue 实现跨层级主题配置共享与响应式更新的轻量方案,关键在于用响应式数据源(ref 或 reactive)配合 provide,并在 inject 处正确订阅变化。
用 provide 注入响应式主题配置
在根组件或布局组件中,使用 ref 或 reactive 创建可变的主题状态,并通过 provide 暴露出去。推荐用 ref,便于后续直接赋值触发响应:
- 定义主题状态:如
const theme = ref('light') - 提供主题及切换方法:如
provide('theme', { theme, setTheme: (val) => theme.value = val }) - 避免直接 provide 普通对象,否则修改属性不会触发响应;必须保证被 inject 的是响应式引用本身
子组件 inject 并自动响应主题变更
任意深层子组件调用 inject 获取主题数据后,可直接在模板中使用 {{ theme.value }},或在 watch 中监听变化:
- 模板中响应式渲染:
<div :class="`theme-${theme.value}`"> <li>逻辑中响应处理:<code>watch(theme, (newVal) => console.log('主题已切为', newVal)) - 注意:inject 返回的是原始 ref,无需再次
toRef或unref,直接用.value即可读写 - 在 provide 组件中,用
watch监听theme,更新 document.documentElement.style: - 例如:
watch(theme, (val) => { document.documentElement.style.setProperty('--primary-color', val === 'dark' ? '#333' : '#007bff'); }) - CSS 中直接使用:
color: var(--primary-color); - provide 的值只对后代组件有效,兄弟组件无法访问;若需多处同步,确保它们共有一个祖先 provider
- 不要在 setup 中多次调用 provide 覆盖同一名字,Vue 不会合并,后一次会完全替换前一次
- inject 默认返回 undefined,建议始终传入默认值或使用
inject('theme', null, true)开启非空断言(Vue 3.3+)
配合 CSS 变量实现样式层动态适配
将主题色映射为 CSS 自定义属性,在根节点动态设置,让纯 CSS 也能响应切换:
立即学习“前端免费学习笔记(深入)”;
避免常见陷阱:丢失响应性与作用域混淆
Provide/Inject 不是全局状态管理,需注意边界和生命周期:










