背景
最近在搭建一个后台管理系统时遇到一个在线切换主题的需求,由于项目使用的是vite + Ant-Design-Vue搭建的,在网上找了一圈发现基于webpack的,就很苦恼。好在看到了这位老哥的帖子,他写的这个vite插件很好的解决了这个需求。
原贴传送门: 基于less和sass的在webpack或vite中的预设多主题的编译方案
使用
这插件使用其实很简单,楼下再细说。先看看效果图:
安装
- npm
npm install @zougt/vite-plugin-theme-preprocessor -D - yarn
yarn add @zougt/vite-plugin-theme-preprocessor -D
配置
- vite.config.ts
import { defineConfig } from "vite";
import path from "path";
import themePreprocessorPlugin from "@zougt/vite-plugin-theme-preprocessor";
export default defineConfig({
plugins: [
// 引入插件
themePreprocessorPlugin({
// 使用Less
less: {
// 此处配置自己的主题文件
multipleScopeVars: [
{
scopeName: "theme-default",
path: path.resolve("src/assets/theme/default.less"),
},
{
scopeName: "theme-dark",
path: path.resolve("src/assets/theme/dark.less"),
},
],
defaultScopeName: "theme-default", // 默认取 multipleScopeVars[0].scopeName
extract: false,// 在生产模式是否抽取独立的主题css文件
},
}),
]
});
- 由于Ant-Design-Vue定制主题需要使用less,所以必须引入Ant-Design-Vue的less文件而不是css文件,具体如何切换为less可以看Ant-Design-Vue的官方文档,此处不多赘述。
- 配置选项具体可参考插件介绍:GitOfZGT/vite-plugin-theme-preprocessor: css theme preprocessor plugin for vite
定制主题
自定义主题文件里可通过覆盖Ant-Design-Vue官方主题变量、使用自定义变量、自定义样式等方式实现主题的定制。以下是两种主题的文件示例:
- default.less
// 引入官方主题
@import "node_modules/ant-design-vue/lib/style/themes/default";
// 修改组件库主题
@primary-color: red;
// 自定义变量
@custom-color: #000000;
// 自定义全局样式
.login_bg {
background: url("@/assets/images/login/bg.jpg") no-repeat 100% 100%;
background-size: cover;
}
- dark.less
// 引入官方主题
@import "node_modules/ant-design-vue/lib/style/themes/dark";
// 修改组件库主题
@primary-color: blue;
// 自定义变量
@custom-color: #ffffff;
// 自定义全局样式
.login_bg {
background: url("@/assets/images/login/bg_daek.jpg") no-repeat 100% 100%;
background-size: cover;
}
切换主题
根据在配置插件时extract选项的值,切换主题时的操作有些许不同。
extract: true
const toggleTheme = (scopeName = "theme-default") => {
let styleLink = document.getElementById("theme-link-tag");
if (styleLink) {
// 假如存在id为theme-link-tag 的link标签,直接修改其href
styleLink.href = `/${scopeName}.css`;
// 注:如果是removeCssScopeName:true移除了主题文件的权重类名,就可以不用修改className 操作
document.documentElement.className = scopeName;
} else {
// 不存在的话,则新建一个
styleLink = document.createElement("link");
styleLink.type = "text/css";
styleLink.rel = "stylesheet";
styleLink.id = "theme-link-tag";
styleLink.href = `/${scopeName}.css`;
// 注:如果是removeCssScopeName:true移除了主题文件的权重类名,就可以不用修改className 操作
document.documentElement.className = scopeName;
document.head.append(styleLink);
}
};
extract: false
const toggleTheme = (scopeName = "theme-default") => {
document.documentElement.className = scopeName;
};
在实际项目操作中,强烈建议将当前主题通过localstorege或者cookie之类的方式缓存至浏览器中,并在用户在关闭浏览器或刷新后重新取出并初始化主题,这样就不会丢失主题影响体验。
也可将本地缓存搭配Vuex使用,将切换主题操作放入actions中,统一管理主题状态。
后记
最后再次感谢zgt_不梦 大佬的插件~