Vue3 零基础每日笔记(071):暗黑模式与主题切换——CSS 变量 + Element Plus 暗黑方案

一、前言

Element Plus 实战篇收官篇。064 篇说过组件库颜色全靠 CSS 变量------本篇吃透这套变量体系:一行引入暗黑模式、一个组合式函数管切换、一个输入框换主题色,让 068 篇的后台骨架白天黑夜都好看。

二、原理一分钟:class 一挂,变量全变

Element Plus 的暗黑方案极其简单:官方提供一份"暗黑变量表",html 标签挂上 class="dark" 时生效。

text 复制代码
:root { --el-bg-color: #ffffff; ... }              ← 亮色(默认)
html.dark { --el-bg-color: #141414; ... }          ← 暗黑(挂 class 后命中)

组件内部全部引用变量(--el-bg-color、--el-text-color-primary......),没有任何组件代码需要改------变量变了,全库换装。我们自己的样式只要也用变量写(064 篇埋的规矩),就能一起切换。

三、三步接入暗黑模式

3.1 引入暗黑变量表

ts 复制代码
// src/main.ts
import 'element-plus/theme-chalk/dark/css-vars.css'   // ★ 暗黑变量表,引一次即可

3.2 封装 useDarkMode 组合式函数

036 篇封装 useToggle 的实战版------主题状态 + 持久化 + class 同步:

ts 复制代码
// src/composables/useDarkMode.ts
import { ref, watchEffect } from 'vue'

// 模块级状态:所有组件共享同一份(和 store 单例同理,039 篇最佳实践)
const THEME_KEY = 'theme'
const isDark = ref(localStorage.getItem(THEME_KEY) === 'dark')

// 自动依赖收集:isDark 变化 → 三个副作用全执行
watchEffect(() => {
  // 1. class 挂在 html(documentElement)上,★ 不是 body
  document.documentElement.classList.toggle('dark', isDark.value)
  // 2. 持久化,刷新不丢(057 篇手动持久化的迷你版)
  localStorage.setItem(THEME_KEY, isDark.value ? 'dark' : 'light')
})

export function useDarkMode() {
  function toggleDark() {
    isDark.value = !isDark.value
  }
  return { isDark, toggleDark }
}

3.3 放进 Layout 顶部栏

vue 复制代码
<!-- Layout.vue header 里加一个开关 -->
<el-switch
  v-model="isDark"
  inline-prompt
  active-icon="Moon"
  inactive-icon="Sunny"
/>

<script setup lang="ts">
import { useDarkMode } from '@/composables/useDarkMode'
const { isDark, toggleDark } = useDarkMode()   // switch 的 v-model 直接绑 isDark
</script>

【截图位置:拨动开关,整个后台瞬间变暗;刷新后仍是暗黑】

四、动态主题色:setProperty 一行搞定

064 篇在 CSS 里覆盖 --el-color-primary 是"写死"的;运行时切换用 JS 设置变量:

vue 复制代码
<template>
  <el-color-picker v-model="primaryColor" @change="setPrimary" />
</template>

<script setup lang="ts">
import { ref } from 'vue'

const primaryColor = ref('#409eff')

function setPrimary(color: string | null) {
  if (!color) return
  const el = document.documentElement
  // ★ 主色一改,按钮/链接/选中态全变
  el.style.setProperty('--el-color-primary', color)
  // 衍生色简单方案:用 color-mix 按比例混白/混黑(现代浏览器支持)
  el.style.setProperty('--el-color-primary-light-3', `color-mix(in srgb, ${color} 70%, white)`)
  el.style.setProperty('--el-color-primary-dark-2', `color-mix(in srgb, ${color} 80%, black)`)
}
</script>

想重启也保持?把 color 一起存 localStorage,初始化时读出来再 setProperty------套路和 isDark 一模一样,留给你练手(系列一贯的"差一步"作业)。

五、自定义样式怎么配合

用变量写的样式自动适配,写死颜色的样式暗黑下刺眼:

css 复制代码
/* ❌ 写死:暗黑下白底白字灾难 */
.my-card { background: #fff; color: #303133; border: 1px solid #dcdfe6; }

/* ✅ 变量:亮暗自动切换 */
.my-card {
  background: var(--el-bg-color);              /* 卡片底色 */
  color: var(--el-text-color-primary);         /* 主文字 */
  border: 1px solid var(--el-border-color);    /* 边框 */
}

常用变量速查:

变量 用途
--el-bg-color / --el-bg-color-page 组件底色 / 页面底色
--el-text-color-primary / regular / secondary 文字三档
--el-border-color 边框
--el-fill-color-light 浅填充(hover 背景)
--el-color-primary 系列 主题色及其衍生

六、踩坑记录

  1. dark class 挂到 body :变量表选择器是 html.dark,挂 body 不生效------必须 document.documentElement
  2. 忘了引 dark/css-vars.css:class 挂了但没暗黑效果------变量表都没加载,调什么都是白搭
  3. 切换按钮绑了 toggleDark 却传了 isDark :el-switch 用 v-model="isDark",toggleDark 适合图标按钮 @click,两种用法别混
  4. 白屏闪一下再变暗:初始化在组件 setup 才挂 class------把 class 恢复逻辑提前到 main.ts / index.html 内联脚本,加载即暗
  5. 部分页面没跟随变暗:那些页面写死了 #fff/#000------全局搜索硬编码色值,替换成 CSS 变量(这是接暗黑的最大工作量)
  6. 第三方图表颜色不适配:ECharts 等自己画 canvas 的库不吃 CSS 变量------切换时把主题色传给图表配置(080 篇会再遇)

七、今日小结

  • 暗黑三步:引 dark/css-vars.css → html 挂 class="dark" → 自己样式用变量
  • 切换器:useDarkMode 组合式函数(模块级单例 + watchEffect + localStorage),036/039 篇的落地样板
  • 动态主题色:setProperty('--el-color-primary', color),衍生色用 color-mix
  • 铁律:自写样式禁止写死色值,全走 --el-xxx 变量

下篇预告

Element Plus 篇完结,进入性能优化篇:组件懒加载与异步组件按需加载------为什么首屏越来越慢?怎么让用户"看到哪加载到哪"?下一篇 072 性能优化开篇。

相关推荐
刘发财1 小时前
前端如何生成10000页PDF文件?
前端·javascript·开源
A接拉起0072 小时前
2026 年 JavaScript 开发者需要了解的知识
前端·javascript·后端
用户11481867894842 小时前
面试官:大屏项目里十几个模块同时渲染上万条数据,怎么做到不卡?
前端·性能优化
前端市界2 小时前
Pro React Admin: 统一工程底座,承载多种应用...
前端·github
葡萄城技术团队2 小时前
dsh-spreadjs-editor 当前支持什么:安装前需要了解的几件事
前端
沫璃染墨2 小时前
《Qt从零入门系列(十三):QSS样式表详解——从选择器与层叠规则到控件美化实战》
开发语言·css·c++·qt·ui·qt6.3·qss
沪上企服通2 小时前
历史账套科目重映射与规则版本重算:旧账梳理的“口径复位”工程
笔记·架构
三*一2 小时前
优化修整算法
前端·javascript·算法
weifont4 小时前
自动化抓取和上架商品:能不动手,就少动手
运维·前端·自动化