可直接用 watchEffect 监听响应式 themeColor 并动态更新 CSS 变量实现主题色实时切换,需在 setup 中定义 ref 主题状态、封装 updateThemeVars 函数批量设置变量、绑定 UI 控件触发变更,并注意 SSR 兼容与 CSS 变量作用域。

可以直接用 watchEffect 监听响应式数据的变化,再动态更新 CSS 变量,从而实现主题色的实时切换。关键不是监听 DOM 或样式本身,而是监听一个控制主题的响应式状态(比如 themeColor),并在副作用中调用 document.documentElement.style.setProperty 更新根元素的 CSS 变量。
定义可响应的主题状态
在 Vue 组件的 setup 中,先声明一个响应式变量来代表当前主题色:
- 推荐使用
ref或computed,例如:const themeColor = ref('blue') - 也可以从
localStorage或 URL 参数初始化,保证刷新后颜色不丢失 - 支持多个预设值(如 'blue' / 'green' / 'purple'),便于后续映射成对应的颜色值
用 watchEffect 同步更新 CSS 变量
在 watchEffect 回调里,根据 themeColor.value 查表或计算出具体 RGB 或 HEX 值,然后批量设置 CSS 变量:
- 例如:
document.documentElement.style.setProperty('--primary-color', '#3b82f6') - 建议统一管理变量名,如
--primary-color、--primary-hover、--bg-base等 - 可封装一个
updateThemeVars(colorKey)函数,把映射逻辑抽离,提升可维护性
绑定 UI 控件触发切换
给按钮、下拉菜单或颜色选择器绑定点击/变更事件,修改 themeColor 的值即可自动触发更新:
- 例如:
<button @click="themeColor = 'green'">绿色主题</button> - 配合
class切换(如:class="{ 'theme-green': themeColor === 'green' }")可同时调整非 CSS 变量控制的样式 - 如果需要过渡动效,可在 CSS 中对
--primary-color添加transition: --primary-color 0.3s(注意:部分浏览器暂不支持变量过渡,可用color、background等具体属性替代)
补充:避免重复设置与 SSR 兼容
在服务端渲染(如 Nuxt)中,document 对象不可用,需加判断;另外首次执行时无需重复设置已存在的变量:
- 用
if (typeof document !== 'undefined')包裹 DOM 操作 - 可在
onMounted中初始化一次默认主题,再让watchEffect负责后续响应 - 若主题配置较复杂(含明暗模式),可将整个主题对象设为响应式,
watchEffect监听其深层变化
不复杂但容易忽略的是:CSS 变量必须作用在能被子元素继承的节点上(通常设在 :root 或 html),且组件内样式要使用 var(--primary-color) 才能生效。