查看: 153|回复: 1

Vue3 + Vite + Ant Design Vue 暗黑模式切换方案:CSS变量与动态Less加载

[复制链接]
发表于 3 小时前 | 显示全部楼层 |阅读模式
在 Vue3 + Vite 项目中使用 Ant Design Vue 时,实现暗黑/亮色主题切换的核心思路是:抽离 CSS 变量,并动态替换框架自带 Less 文件。本文记录具体实现步骤和代码。

一、全局 CSS 变量定义

在 src 下新建 vars.css 文件,声明一套基于 :root 的 CSS 变量,用于控制页面背景、文字颜色、边框色等。例如:
  1. :root {
  2.   --page-bg-color: #fff;
  3.   --head-bg-color: rgba(255, 255, 255, 0.7);
  4.   --text-color: rgba(0, 0, 0, 0.85);
  5.   --line-color: #e8e8e8;
  6.   --content-bg-color: #f0f2f5;
  7. }
复制代码
二、准备两套入口 Less 文件

分别对应暗黑和亮色模式,放在 src/less 目录下。

light.less:
  1. @import "../../node_modules/ant-design-vue/dist/antd.less";
  2. @import "./index.css";
  3. @import "./base.less";
  4. @import "./vars.css";
复制代码

dark.less:
  1. @import "../../node_modules/ant-design-vue/dist/antd.dark.less";
  2. @import "./index.css";
  3. @import "./base.less";
  4. @import "./vars.css";
复制代码

其中 index.css 和 base.less 是项目自己的样式文件,可根据需要调整。关键是通过 @import 引入对应版本的 Ant Design 主题文件。

三、组件样式中使用 CSS 变量

在组件或页面 Less/CSS 中,用 CSS 变量替换固定色值。例如:
  1. .pagemodal {
  2.   background: white; /* 降级方案 */
  3.   background: var(--page-bg-color);
  4.   border-radius: 5px;
  5.   padding: 10px;
  6. }
复制代码
这样当 --page-bg-color 变化时,组件样式自动跟随。

四、编写主题切换工具函数

创建 themeUtils.ts,封装两个核心方法。

1. changeTheme:动态创建 style 标签并注入 Less 编译后的 CSS 字符串(实际工程中 Less 文件经过 Vite 预处理后导出为 CSS 字符串)。
  1. export const changeTheme = (theme: string) => {
  2.   const head = document.head;
  3.   document.getElementById("theme")?.remove(); // 移除旧主题样式
  4.   const styleDom = document.createElement("style");
  5.   styleDom.id = "theme";
  6.   styleDom.innerHTML = theme;
  7.   head.appendChild(styleDom);
  8. };
复制代码

2. changeCss:直接操作 body.style 的 setProperty 方法,更新 CSS 变量值。
  1. export const changeCss = (css: string, value: string) => {
  2.   const body = document.body.style;
  3.   body.setProperty(css, value);
  4. };
复制代码

五、整合暗黑/亮色切换函数

先引入编译好的 Less 文件(Vite 默认支持将 .less 作为模块导入)。
  1. import light from "../less/light.less";
  2. import dark from "../less/dark.less";
复制代码

export const DarkMode = (isDark: boolean) => {
  if (isDark) {
    changeTheme(dark);
    changeCss("--page-bg-color", "#141414");
    changeCss("--head-bg-color", "rgba(0, 0, 0, 0.5)");
    changeCss("--line-color", "#2e2e2e");
    changeCss("--content-bg-color", "rgb(255 255 255 / 4%)");
    changeCss("--text-color", "rgba(255, 255, 255, 0.85)");
  } else {
    changeTheme(light);
    changeCss("--page-bg-color", "white");
    changeCss("--head-bg-color", "rgba(255, 255, 255, 0.7)");
    changeCss("--line-color", "#e8e8e8");
    changeCss("--content-bg-color", "#f0f2f5");
    changeCss("--text-color", "rgba(0, 0, 0, 0.85)");
  }
};
[/code]

注意:导入 Less 文件时,Vite 会将它们编译为独立的 CSS 块,调用 changeTheme 时传入的是该 CSS 字符串。

六、调用示例

在应用入口或主题切换按钮中:
  1. // 切换为暗黑模式
  2. DarkMode(true);
  3. // 恢复为亮色模式
  4. DarkMode(false);
复制代码

七、注意事项

- Vite 的 Less 导入需确保 less 和 less-loader 已安装,且配置正确。
- CSS 变量降级写法(如 background: white;)可兼容不支持 CSS 变量的旧浏览器,但现代项目一般无需。
- 如果多个组件都依赖这些变量,建议统一在 vars.css 中声明,并通过 import 引入。
- 此方案同时解决了 Ant Design Vue 组件内部样式的黑暗模式和自定义变量的同步切换。

总结:本方案将 Ant Design Vue 的暗黑主题与自定义 CSS 变量结合,通过动态替换 style 标签和更新 CSS 变量实现即时切换,代码干净且易于维护,适合 Vue3 + Vite 项目快速复用。
回复

使用道具 举报

发表于 3 小时前 | 显示全部楼层

Re: Vue3 + Vite + Ant Design Vue 暗黑模式切换方案:CSS变量与动态Less加载

感谢分享这么完整的实现方案!用CSS变量配合动态Less加载确实是Vue3+Vite项目里切换Ant Design Vue主题比较灵活的做法,既保留了框架完整的主题变量,又能自定义全局颜色,维护起来也很清晰。特别喜欢你把两套Less入口文件分开组织,切换时用changeTheme整体替换框架样式,再用changeCss单独覆盖自定义CSS变量,这样职责非常明确。 一个小建议:在`DarkMode`函数里,`changeCss`每次都会调用多次setProperty,如果未来自定义CSS变量增多,可以考虑把不同主题的变量值抽成单独的对象,然后在函数里遍历设置,代码会更简洁一些。另外如果Less文件较大,动态创建style标签时可能需要注意一下加载性能,不过Vite编译后的CSS字符串应该不大,影响有限。 请问实际项目中你是用Vite的less插件直接导入.less文件吗?还是做了其他预处理?想了解一下这块在打包时的具体效果。再次感谢分享!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-6-12 11:09 , Processed in 0.030316 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部