上次在nextjs开发的博客中添加了深色主题后(有网友想要的nextjs博客源码已经上传到github了,blog-template-nextjs),学习了vue3和vite开发环境最近几个月。就在那时,我考虑将黑暗主题引入我的演示项目,这个想法变成了现实。
在线预览:门户 从页面上的下拉菜单更改主题。目前仅准备黑白、全白和深色。
代码仓库:vue3-admin
示例
登录
- 深色主题
- 白色主题
工作台
- 深色主题
- 白色模式
意识到
原理:通过antd-theme-generator
库,提取color.less
中ant-design-vue中的样式和项目中使用的样式(不用写),然后使用getLessVars
方法一一添加多个主题1 将变量配置打包在json文件中,在项目中引用。最后在生产环境中通过调用方法less.modifyVars
改变全局样式(less移除当前标签style
,并根据指定的变量值生成新的样式标签)
核心代码
antd-theme-generator
作者提供的antd-theme-webpack-plugin
不能在vite环境中使用,所以这里提供一个简单版本的vite插件替换:vite-plugin-antd-theme。主要包括生成json和自动调用generateTheme
方法的行为。
安装vite-plugin-antd-theme
yarn add vite-plugin-antd-theme -D
antd-theme-generator
主动依赖了antd-theme-generator
,因此主项目不需要重新安装,也不需要从中导入方法,并且vite-plugin-antd-theme
已经导出了antd-theme-generator
所需的输入参数类型。
vite.config.ts
import path from 'path';
import { UserConfigExport, ConfigEnv } from 'vite';
import viteAntdTheme, { ThemeEntry, AntdThemeOptions } from 'vite-plugin-antd-theme';
const themesEntry: Array<ThemeEntry> = [
// 暗黑主题
{
entryPath: './node_modules/ant-design-vue/lib/style/themes/dark.less',
outputName: 'dark',
outputPath: './src/config'
},
// 默认主题
{
entryPath: './src/styles/vars.less',
outputName: 'light',
outputPath: './src/config'
},
// 紧凑主题
{
entryPath: './node_modules/ant-design-vue/lib/style/themes/compact.less',
outputName: 'compact',
outputPath: './src/config'
}
];
const options: AntdThemeOptions = {
themesEntry,
// 是否提取全部变量,默认false,优先级低于设置themeVariables
allVariables: true,
// 以下是antd-theme-generator配置项
antDir: path.join(__dirname, './node_modules/ant-design-vue'),
stylesDir: path.join(__dirname, './src'), // all files with .less extension will be processed
varFile: path.join(__dirname, './src/styles/vars.less'), // default path is Ant Design default.less file
themeVariables: [],
outputFilePath: path.join(__dirname, './public/static/color.less'), // if provided, file will be created with generated less/styles
customColorRegexArray: [/^fade\(.*\)$/] // An array of regex codes to match your custom color variable values so that code can identify that it's a valid color. Make sure your regex does not adds false positives.
};
export default ({ command }: ConfigEnv): UserConfigExport => {
return {
plugins: [
viteAntdTheme(options)
]
};
};
显然默认配置项还是很多,计划在1.0.2之后的版本中封装这些默认配置项。
样式/vars.less
// This file will contain all varibales, our custom varibales and
//those from Ant Design which we want to override.
@import '../../node_modules/ant-design-vue/lib/style/themes/default.less';
@primary-color: @green-6;
@select-item-selected-option-color: @primary-color;
@processing-color: @primary-color;
@select-item-selected-bg: @background-color-base;
@secondary-color: @primary-color;
@skeleton-color: @primary-color;
@btn-primary-bg: @primary-color;
:root {
--PC: @primary-color;
}
您可以在此处调整主题颜色。变量名的含义主要参考ant-design-vue。
index.html
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
<link rel="stylesheet/less" type="text/css" href="/static/color.less" />
<script src="/static/libs/less.min.js"></script>
</body>
这里需要准备一个运行在浏览器端的2.7.3版本的less,用于在线自定义主题样式。项目运行时会自动生成color.less(bug:目前第一次运行时发现。build时提示color.less没有问题,尚未解决。目前最好dev构建早点完成)。
main.ts
这里只介绍一下and world的less风格。
import 'ant-design-vue/dist/antd.less';
import Final from '@/config/keys';
import darkVars from '@/config/dark.json';
import lightVars from '@/config/light.json';
export type Themes = 'dark' | 'light' | 'mix';
export interface SettingStateType {
// 主题
theme: Themes;
}
// 手动调用全局的modifyVars
const lessHandler = (themeName: Themes) => {
switch (themeName) {
case 'dark': {
(window as any).less.modifyVars(darkVars);
break;
}
case 'light': {
(window as any).less.modifyVars(lightVars);
break;
}
case 'mix': {
(window as any).less.modifyVars(lightVars);
}
}
};
// 读取缓存的主题
const cacheTheme = localStorage.getItem(Final.THEME);
const state: SettingStateType = {
theme:
(cacheTheme === 'dark' && 'dark') ||
(cacheTheme === 'light' && 'light') ||
(cacheTheme === 'mix' && 'mix') ||
'dark'
};
// 首次自动修改主题
lessHandler(state.theme);
const mutations = {
// 切换主题
themeChanged(state: SettingStateType, payload: { theme: Themes }): void {
state.theme = payload.theme;
localStorage.setItem(Final.THEME, payload.theme);
lessHandler(payload.theme);
}
};
const actions = {};
export default {
namespaced: true,
state,
mutations,
actions
};
vue3-admin
的实现是提交一个mutation来自动激活主题更改逻辑。
至此功能就大致实现了,只需要添加触发器即可。
在文章最后
vue3-admin
是一个使用vue3系列、Vite开发环境、纯tsx语法开发的后端管理项目。虽然Vue主要提倡模板语法,但希望你能通过这个方法学到一些东西。特别是,笔者认为可以拉近react和vue的距离,并且vscode可以在tsx写入过程中提供更友好的提示。关于写tsx时的注意事项、转换项以及一些陷阱,项目中有一些注释。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。