前言
之前的菜单栏想按照BuildAdmin的模式,来实现一个 Terminal 终端。
我以为是和CRT这样交互式终端,结果是类似于预编辑的命令脚本,然后在远程服务器上执行,和预想的结果不太一样。如果想要实现我的预想效果,还要涉及websocket。
其实到这里也还好,只不过后来的terminal库没有研究明白,所以就直接将 terminal 的图标,直接换成了暗黑模式切换图标,借此实现了BuildAdmin暗黑模式和正常模式的切换。
切换按钮
首先设计暗黑模式的切换按钮,我直接使用的 Element Plus 的 el-switch 开关组件。我想在亮光模式下图标是个小太阳,暗黑模式下是月亮,所以需要用到自定义图标的功能,直接复制 Element Plus 官网给出的代码。
在这里我踩了一个坑自定义图标这个功能需要 Element Plus 最低版本是2.4.4,当时我没看到tag提示,就一直没有显示图标,后来排查了很久才发现我使用的是2.2.1版本,后来升级了最新版本才能正常显示图标。
查看 Element Plus 版本和升级的指令如下:
代码语言:shell复制npm show element-plus version
npm install element-plus@latest
开关图标
去图标网站下载 moon 和 light 的 svg 图标,当然也可以使用 Element Plus 的图标,使用方法在官网有说明。这里我下载的 svg,然后分别在 active-action 和 inactive-action 插槽中,插入自定义的 Icon 图标。
代码语言:html复制<template>
<el-switch v-model="is_switch" size="small"
style="--el-switch-on-color: #2C2C2C; --el-switch-off-color: #CFD3DC"
>
<template #active-action>
<Icon name="local-moon" size="12" />
</template>
<template #inactive-action>
<Icon name="local-light" size="12" />
</template>
</el-switch>
</template>
在 el-switch 组件中绑定 is_switch 响应式变量,然后在开关切换时会自动修改这个变量。
代码语言:JavaScript复制<script setup lang="ts">
import { ref } from 'vue'
const is_switch = ref(false)
</script>
这里要注意的是,is_switch 要设置为false,这样在开关初始位置才能在左侧。然后官网代码中的图标样式过大,所以将 size 属性设置为 small,同时通过 style 的 --el-switch-on-color 和 --el-switch-off-color 设置开关的背景色。
最后实现效果如下:
暗黑模式
接下来就是实现暗黑模式,暗黑模式的原理就是在 html 节点上添加一个名为 dark 的 class
然后我们设置 dark 的 css 样式即可。我们可以在 main.ts 中引入 Element Plus 官方定义的 css,但是有时候一些元素覆盖不到,所以我们自定义样式。
代码语言:typescript复制import 'element-plus/theme-chalk/dark/css-vars.css'
// 自定义
import './styles/dark/dark.scss'
在 dark.scss 中,先定义全局的样式变量:
代码语言:css复制/* 全局默认模式颜色定义 */
:root {
--background-color: white;
--background-color-layout: #F5F5F5;
--text-color: black;
--primary-color: blue;
--secondary-color: gray;
--border-color: #ddd;
--link-color: blue;
--button-background-color: #007bff;
--button-text-color: white;
}
/* 暗黑模式颜色覆盖 */
html.dark {
--background-color: #121212;
--background-color-layout: #101112;
--text-color: white;
--primary-color: #1e90ff;
--secondary-color: #aaa;
--border-color: #333;
--link-color: #1e90ff;
--button-background-color: #333;
--button-text-color: white;
}
/* 全局应用背景和文字颜色 */
body {
background-color: var(--background-color);
color: var(--text-color);
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
}
其中,root 和 dark 的变量都是相同的,分别代表亮光和暗黑模式下变量的值。然后在各个组件中,将 background-color 使用上面的变量代替。
接着是在 dark.scss 中定义一些通用组件的文本和背景颜色。
代码语言:css复制/* 通用元素样式 */
p, a, h1, h2, h3, span, div, i, svg {
color: var(--text-color);
}
.dark li {
background-color: var(--background-color);
}
/* 按钮样式 */
button {
background-color: var(--button-background-color);
color: var(--button-text-color);
border: none;
padding: 10px 20px;
cursor: pointer;
transition: background-color 0.3s ease;
}
button:hover {
background-color: var(--primary-color);
}
/* 表单输入框样式 */
input[type="text"], textarea {
width: 100%;
padding: 10px;
border: 1px solid var(--border-color);
background-color: var(--background-color);
color: var(--text-color);
}
input[type="text"]:focus, textarea:focus {
border-color: var(--primary-color);
outline: none;
}
/* 暗黑模式下元素覆盖样式 */
.dark body, .dark p, .dark a, .dark h1, .dark h2, .dark h3, .dark span, .dark div {
color: var(--text-color) !important;
}
.dark button {
background-color: var(--button-background-color) !important;
color: var(--button-text-color) !important;
}
.dark input[type="text"], .dark textarea {
background-color: var(--background-color) !important;
color: var(--text-color) !important;
border-color: var(--border-color) !important;
}
开关
如果想要在亮光模式和暗黑模式动态切换,这里建议使用 @vue/core 库,这个库算是一个工具库,之前在实现 tabs 栏的时候,用来获取鼠标的坐标。详情可参考文章BuildAdmin08:导航栏tab的滑动块如何实现。
这里主要使用 useDark 和 useToggle 来切换暗黑模式。useDark 是一个封装了 Boolean 类型的对象,用来表示是否已经开启暗黑模式(html的class是否添加dark)。
而useToggle就是用来改变useDark的 Boolean 变量,从而控制模式之间的切换。
代码语言:javascript复制import { useDark, useToggle } from '@vueuse/core'
const isDark = useDark()
if (isDark.value == true) {
useToggle(isDark)()
}
const toggleDark = useToggle(isDark)
在上面的代码中增加了一个判断,原因就是在暗黑模式下刷新页面,开关已经变成亮光了,但是还是处于暗黑模式下。
分析原因就是 useDark 还是为 ture,所以需要增加判断,手动使用 useToggle 来将其改变为 false,useToggle 返回的是一个函数,所以想要调用还需要后面增加一个括号。下面的 toggleDark返回的就是一个函数,然后绑定到开关的 change 事件上。
最终代码:
切换效果:
细节修复
例如有的图标是 Element Plus 的,有的是本地svg,还有其他的,所以就会出现图标还是黑色的情况。
如果想解决这些颜色问题,就需要对 dark.scss 进行设计。这里对 dark 模式下的 svg 和 fa 标签进行颜色设置。
代码语言:css复制.dark {
& svg {
color: white !important;
}
& .fa {
color: white !important;
}
}
最终的图标效果:
结语
这就是基于 Element Plus 实现的暗黑模式,当然还有很多细节可以修复,包括设计一些切换时的动画等等,这个下篇文章可以探讨一下。