共计 4215 个字符,预计需要花费 11 分钟才能阅读完成。
在上次在 nextjs 开发的博客中增加了暗黑主题后(一些网友想要的 nextjs 博客源码曾经上传到 github,blog-template-nextjs),这几个月在学习应用 vue3 及 vite 开发环境时,想着把暗黑主题也带到我的 demo 我的项目中,并构想实现了。
形容 :在 nextjs 中对 antd 的亮白和暗黑主题切换实际。
在线预览 :传送门 在页面的下拉菜单切换主题,目前只筹备了黑白,全白和暗黑三种。
代码仓库:vue3-admin
预览图
登录
- 暗黑主题
- 红色主题
工作台
- 暗黑主题
- 红色模式
实现
原理:通过 antd-theme-generator
库,将 ant-design-vue 中的款式及我的项目中应用到的款式(less 编写)抽出放到 color.less
中,再通过 getLessVars
办法挨个将多个主题变量配置打包成 json 文件并在我的项目中援用,最初在生产环境中通过调用 less.modifyVars
办法批改全局款式(less 会依据提供的变量值,删除以后的 style
标签,从新生成新的款式标签)
外围代码
因为是在 vite 环境中 antd-theme-generator
作者提供的 antd-theme-webpack-plugin
没法应用,所以这里写了一个简略版的 vite 插件替换:vite-plugin-antd-theme。次要是封装了一下生成 json 的行为和主动调用 generateTheme
办法。
装置 vite-plugin-antd-theme
yarn add vite-plugin-antd-theme -D
vite-plugin-antd-theme
中已被动依赖了 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 之后的版本会将默认项封装。
styles/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 的问题,暂未修复,目前最好在 build 前都跑一遍 dev)。
main.ts
这里全局引入 antd 的 less 款式即可。
import 'ant-design-vue/dist/antd.less';
store/modules/setting.ts
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 之间的间隔,而且 tsx 编写的过程,vscode 能更敌对的提醒。对于 tsx 编写的留神项、转换项以及一些小坑,都在我的项目中有局部正文了。