动态主题切换是针对用户体验的常见的功能之一,我们可以自己实现如暗黑模式、明亮模式的切换,也可以利用 Element Plus 默认支持的强大动态主题方案实现。这里我们探讨的是后者通过 CSS 变量设置的方案。
1 组件准备
1.1 修改 Navbar 组件
在 src/layout/***ponents/Navbar.vue 中添加设置按钮,代码如下:
//src/layout/***ponents/Navbar.vue
<template>
<div class="navbar" flex>
<hamburger
@toggleCollapse="toggleSidebar"
:collapse="sidebar.opened"
></hamburger>
<BreadCrumb></BreadCrumb>
<div flex justify-end flex-1 items-center mr-20px>
<screenfull mx-5px></screenfull>
<el-tooltip content="ChangeSize" placement="bottom">
<size-select></size-select>
</el-tooltip>
<svg-icon
icon-name="ant-design:setting-outlined"
size-2em
@click="openShowSetting"
></svg-icon>
</div>
</div>
</template>
<style scoped lang="scss">
.navbar {
@apply h-[var(--navbar-height)];
}
</style>
<script lang="ts" setup>
import { useAppStore } from "@/stores/app";
// 在解构的时候要考虑值是不是对象,如果非对象解构出来就 丧失响应式了
const { toggleSidebar, sidebar } = useAppStore();
const emit = defineEmits<{
(event: "showSetting", isShow: boolean): void;
}>();
const openShowSetting = () => {
emit("showSetting", true);
};
</script>
1.2 封装 RightPanel 组件
我们希望点击设置按钮后,右侧出现抽屉面板。在 src/***ponents 下新建 RightPanel,然后新建 index.vue 文件,代码如下:
//src/***ponents/RightPanel/index.vue
<template>
<el-drawer
:model-value="modelValue"
:direction="direction"
:title="title"
@close="handleClose"
>
<slot></slot>
</el-drawer>
</template>
<script lang="ts" setup>
import type { DrawerProps } from "element-plus";
import type { PropType } from "vue";
defineProps({
modelValue: {
type: Boolean,
default: false
},
direction: {
type: String as PropType<DrawerProps["direction"]>,
default: "rtl"
},
title: {
type: String,
default: ""
}
});
const emit = defineEmits(["update:modelValue"]);
const handleClose = () => {
emit("update:modelValue", false);
};
</script>
1.3 封装 ThemePicker 组件
在 src/***ponents 下新建 ThemePicker/index.vue 用来选择主题颜色,代码如下:
//src/***ponents/ThemeOicker/index.vue
<template>
<el-color-picker v-model="theme" :predefine="predefineColors" />
</template>
<script lang="ts" setup>
import { useSettingStore } from "@/stores/settings";
const store = useSettingStore();
const theme = ref(store.settings.theme);
const predefineColors = [
"#ff4500",
"#ff8c00",
"#ffd700",
"#90ee90",
"#00ced1",
"#1e90ff",
"#c71585"
];
watch(theme, (newValue) => {
store.changeSetting({ key: "theme", va