寻星网盘-3-全局黑夜模式、明亮模式主题切换
本文介绍了主题切换功能的实现方案,通过el-switch组件实现明亮/黑夜模式切换。关键实现包括:1)使用localStorage存储主题偏好;2)通过data-theme属性和CSS变量定义两种主题样式;3)在全局样式文件中设置颜色变量。功能初始化时读取本地存储的主题设置,切换时更新DOM属性并派发自定义事件通知其他组件。该方案实现了主题的全局统一切换,并保持用户偏好。
一、项目背景
新目标:完成设置页面中“主题模式”切换功能,支持在明亮模式与黑夜模式之间自由切换。通过设置全局theme实现。
二、功能实现
主题模式的切换功能位于 SettingsView 中。因此,第一步需要梳理 SettingsView 内部的控制逻辑,明确当前页面是如何实现模式切换的,包括状态的存储方式(如 localStorage 或全局状态管理)、切换触发组件(如下拉框、开关按钮)以及样式应用机制(通过 class 切换或 CSS 变量)。在此基础上,再进行功能实现和优化。
<el-switch v-model="isDarkMode" @change="handleThemeChange">
<template #active-action>
<span class="custom-active-action"><el-icon><MoonNight /></el-icon></span>
</template>
<template #inactive-action>
<span class="custom-inactive-action"><el-icon><Sunrise /></el-icon></span>
</template>
</el-switch>
在本功能中,采用 el-switch 组件作为主题模式的切换控件。为了提升界面美观度,滑块部分引入了 el-icon 图标进行装饰,也可以根据实际需求,自行替换为更符合设计风格的图标或元素。
import { Sunrise, MoonNight } from '@element-plus/icons-vue'
export default {
components:{
Sunrise,
MoonNight
},
setup(props, { emit }) {
const isDarkMode = ref(false)
// 初始化主题
const initTheme = () => {
const savedTheme = localStorage.getItem('theme') || 'light'
isDarkMode.value = savedTheme === 'dark'
document.documentElement.setAttribute('data-theme', savedTheme)
}
// 页面加载时初始化主题
initTheme()
const handleThemeChange = (value) => {
const theme = value ? 'dark' : 'light'
document.documentElement.setAttribute('data-theme', theme)
localStorage.setItem('theme', theme)
isDarkMode.value = value
}
}
此处仅展示了关键代码片段。由于示例中使用到了 icon 图标,请确保在文件中正确导入相关图标,并在 components 中完成声明后再进行使用。
主题的初始化逻辑如下:
-
优先从
localStorage中读取已保存的theme值; -
如果用户从未使用过或未曾设置过主题,则默认使用 明亮模式(light);
-
根据获取到的
theme值,确定el-switch的初始状态(true表示深色模式,false表示明亮模式)。
document.documentElement.setAttribute('data-theme', savedTheme)
这句看不懂没关系,先放着,后面有讲。
当前已经完成了全局主题颜色的配置,下一步是让所有页面根据主题自动切换颜色。
-
创建
theme.css文件,作为全局样式文件,定义明亮模式和深色模式下的各类颜色变量;* 明亮模式 - 默认样式 */ :root { --el-bg-color: #ffffff; --el-text-color-primary: #303133; --el-text-color-regular: #606266; --el-text-color-secondary: #909399; --el-text-color-placeholder: #c0c4cc; --el-border-color-base: #dcdfe6; --el-border-color-light: #e4e7ed; --el-border-color-lighter: #ebeef5; --el-border-color-extra-light: #f2f6fc; } /* 黑夜模式 */ [data-theme="dark"] { --el-bg-color: #1a1a1a; --el-text-color-primary: #ffffff; --el-text-color-regular: #e4e7ed; --el-text-color-secondary: #cfd3dc; --el-text-color-placeholder: #a3a6ad; --el-border-color-base: #4c4d4f; --el-border-color-light: #414243; --el-border-color-lighter: #363637; --el-border-color-extra-light: #2b2b2c; } /* CloudView 主题样式 */ [data-theme="dark"] .cloud-container { background-color: var(--el-fill-color-base) !important; } [data-theme="dark"] .sidebar { background-color: var(--el-bg-color) !important; border-color: var(--el-border-color-base) !important; } [data-theme="dark"] .main-content { background-color: var(--el-bg-color) !important; }上述内容仅展示了
theme.css中的部分代码,暂时不必完全理解,后面会进行详细讲解。 -
在
main.js中引入该样式文件,确保整个项目的组件和页面都能访问到这些全局样式,实现统一的主题响应。import './styles/theme.css'
至此,全局样式配置已完成,主题切换功能已经可以在整个项目中生效。功能效果示意图如下所示:


三、详细讲解
1.document.documentElement.setAttribute('data-theme', savedTheme)
document.documentElement.setAttribute('data-theme', savedTheme)
代码分解:
- document:代表整个 HTML 文档
- documentElement:指的是文档的根元素,也就是 <html> 标签
- setAttribute():设置 HTML 元素的属性
- 'data-theme':属性名
- savedTheme:属性值('dark' 或 'light')
这行代码会在 <html> 标签上添加一个 data-theme 属性
明亮模式时:
<html data-theme="light">
<!-- 页面内容 -->
</html>
黑夜模式时:
<html data-theme="dark">
<!-- 页面内容 -->
</html>
有了这个属性,我们就可以使用 CSS 选择器来应用不同的样式:
/* 明亮模式样式(默认) */
.title {
background-color: white;
color: black;
}
/* 黑夜模式样式 */
[data-theme="dark"] .title {
background-color: black;
color: white;
}
通过这种方式,可以针对同一个 class,根据当前主题应用不同的样式,实现主题间的样式切换。
2.:root
:root {
--el-bg-color: #ffffff;
--el-text-color-primary: #303133;
--el-border-color-extra-light: #f2f6fc;
}
:root 指的是根元素,在 HTML 中,根元素就是 <html> 标签,所以 :root 等价于 html 选择器。示例如下:
<html> <!-- 这就是根元素 -->
<body>
<div>内容</div>
</body>
</html>
:root {
/* 这里的样式会应用到 <html> 标签 */
}
/* 等价于 */
html {
/* 同样的效果 */
}
3.--el-bg-color: #ffffff;
--el-bg-color: #ffffff;
--el-bg-color: #ffffff; 只是定义了一个 CSS 变量,它本身不会改变任何元素的背景颜色,需要使用这个变量才能生效。使用方法如下示例:
:root {
--el-bg-color: #ffffff; /* 定义变量 */
}
/* 使用变量 */
.my-element {
background-color: var(--el-bg-color); /* 使用变量 */
}
/* 实际效果 */
.my-element {
background-color: #ffffff; /* 背景变为 #ffffff */
}
4.为什么是--el-bg-color?这是固定的吗?还是可以起别的名字?
可以起别的名字!但建议保持 --el- 前缀
/* CSS 变量命名规则: */
:root {
/* 可以自定义变量名 */
--my-bg-color: #ffffff;
--primary-color: #409eff;
--custom-text-color: #333333;
/* Element Plus 官方变量名 */
--el-bg-color: #ffffff;
--el-text-color-primary: #303133;
}
/* 使用自定义变量: */
.my-element {
background-color: var(--my-bg-color);
color: var(--custom-text-color);
}
为什么建议保持 --el- 前缀:
- Element Plus 组件使用这些变量
- 保持一致性,便于维护
- 避免与 Element Plus 内部变量冲突
更多推荐
所有评论(0)