切换主题通常是日常模式和暗夜模式,通过页面按钮点击使页面呈色调为白色或黑色。
当前使用 sass ,配合 Pinia 去做到简易的切换主题功能。
sass
使用 sass 去配置页面主题对应的 css 样式
新建 theme.scss、handle.scss 文件
- theme.scss 主要是设置主题颜色和制定对应样式
- handle.scss 去设置使用切换对应样式的方法
themes.scss
其中 light 为日常主题,为白色调; dark 为暗夜主题,为黑色调。在里面设置背景颜色、字体颜色等样式。
// theme.scss
$themes: (
light: (
background_color: #fff,//背景色
text-color: rgba(0, 0, 0, 0.65), // 主文本色
),
dark: (
background_color: #121316,//背景
text-color: #fff, // 主文本色
)
);
handle.scss
定义好要在 vue 文件 style 中使用的方法
// handle.scss
@import "./themes.scss";
//遍历主题map
@mixin themeify {
@each $theme-name, $theme-map in $themes {
//!global 把局部变量强升为全局变量
$theme-map: $theme-map !global;
//判断html的data-theme的属性值 #{}是sass的插值表达式
//& sass嵌套里的父容器标识 @content是混合器插槽,像vue的slot
[data-theme="#{$theme-name}"] & {
@content;
}
}
}
//声明一个根据Key获取颜色的function
@function themed($key) {
@return map-get($theme-map, $key);
}
//获取background-color背景颜色
@mixin background_color($color) {
@include themeify {
background-color: themed($color)!important;
}
}
//获取字体颜色
@mixin font_color($color) {
@include themeify {
color: themed($color)!important;
}
}
vite.config.ts
在 vite.config.ts 配置使用 上面的 handle.scss 文件,做到项目全局使用文件中 scss 的方法。
css: {
preprocessorOptions: {
scss: {
additionalData: '@import "@/assets/styles/constant.scss";@import "@/assets/styles/handle.scss";'
}
}
}
使用 sass 样式
在 style 中使用 @include 调用 handle.scss 中用 @mixin 定义好的方法。 其中 @minxin 方法传的值为 themes.scss 中定义对应样式的属性名
<style>
.box {
@include background_color("background_color");
@include background_color("font_color");
}
</style>
Pinia
Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态。
在页面组件中设置一个按钮,利用 Pinia 的状态管理,绑定方法做到全局切换样式
setting.ts
配置公共状态管理文件
利用 window.document.documentElement.setAttribute('data-theme', 'dark') 设置 html 的 attribute 属性
import { defineStore } from "pinia";
import { ref, computed } from "vue";
export const useSettingStore = defineStore(
"setting",
() => {
let title = ref<string>("不知名网站");
let theme = ref<string>("dark");
const titleDescribe = computed(() => `${title.value}是该网页的主题名`);
// 主要部分================================
function changeSettingTheme(e: string) {
theme.value = e;
window.document.documentElement.setAttribute("data-theme", e);
}
// =======================================
function setTitle(e: string) {
title.value = e;
}
return { title, theme, titleDescribe, changeSettingTheme, setTitle };
},
// 做持久化存储
{
persist: {
enabled: true,
// localStorage
strategies: [{ key: 'theme', storage: sessionStorage, paths: ["theme"] }],
},
}
);
其中如果刷新页面的话,状态就会恢复初始状态。这个时候需要使用到 数据持久化存储 去保持主题的变化。
调用
<script setup lang="ts">
import { reactive, ref, onMounted } from "vue";
import { useSettingStore } from "@/stores/setting";
const settingStore = useSettingStore();
let inputChecked = ref<boolean>(false);
// 主要部分 ================
const changeTheme = () => {
inputChecked.value = !inputChecked.value;
let theme = inputChecked.value ? "dark" : "light";
settingStore.changeSettingTheme(theme);
};
// ========================
onMounted(() => {
inputChecked.value = settingStore.theme !== "dark";
changeTheme();
});
</script>