在 vue 3 中,watcheffect 通过响应式 ref 控制暗黑模式并同步 css 变量,再由图表库(如 echarts)基于变量或 theme 属性重绘;需封装系统偏好为可读写 ref、持久化 localstorage、避免异步操作以确保样式与图表同步更新。

在 Vue 3 中,watchEffect 本身不直接“侦听”暗黑模式或图表色彩,而是通过响应式状态驱动 CSS 变量更新,再由图表库(如 ECharts)基于这些变量重绘。关键在于:把暗黑模式开关和主题色配置变成响应式数据,用 watchEffect 自动同步到全局样式层,图表组件再通过 class 或 theme 属性感知变化并刷新视觉。
把暗黑模式状态转为 ref 响应式源
不能监听 prefers-color-scheme 媒体查询本身,但可以封装成可读写的 ref:
- 定义
isDark = ref(false)作为统一控制开关 - 初始化时读取系统偏好:
isDark.value = window.matchMedia('(prefers-color-scheme: dark)').matches - 监听媒体变化并更新 ref:
matchMedia.addEventListener('change', e => isDark.value = e.matches) - 用户手动切换时也只改
isDark.value,保持单一数据源
用 watchEffect 同步写入主题相关的 CSS 变量
在 setup 或 onMounted 中调用 watchEffect,根据 isDark 动态设置变量值:
- 主色、背景、文字等变量统一加前缀,例如:
--chart-primary、--chart-bg、--chart-text - 在
watchEffect内部读取isDark.value,计算对应颜色字符串并写入:document.documentElement.style.setProperty('--chart-bg', isDark.value ? '#121212' : '#ffffff') - 确保所有变量都设回退值,比如
background-color: var(--chart-bg, #fff),避免未定义时样式崩溃
让图表组件响应主题变化并重绘
ECharts 等库不自动监听 CSS 变量,需主动触发更新:
- 若使用
vue-echarts,配合provide/inject将当前主题名(如'light'或'dark')注入子组件,在图表内监听该值变化后调用chart.setOption(option, { notMerge: true }) - 更轻量的方式:给
<vchart></vchart>绑定:theme="isDark ? 'dark' : 'light'",利用其内置的 theme 切换机制自动重绘 - 对原生 ECharts 实例,可在
watchEffect更新完 CSS 变量后,手动调用chart.getDom().style.color = 'var(--chart-text)'(仅限简单样式),复杂图表仍推荐 setOption
持久化与边界处理
避免刷新丢失状态,同时防止竞态干扰渲染:
- 将
isDark.value存入localStorage,页面加载时优先读取本地值,再 fallback 到系统偏好 -
watchEffect内不要做异步操作(如 await API),否则可能打断样式同步时机 - 如果图表有动画或过渡,可在
watchEffect中加nextTick确保 DOM 更新完成后再触发重绘
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











