前言:
根据公司的要求,在一个创建的基础的系统上加入系统主题(实现白天和黑夜的系统主题切换,另外在暗黑主题下,局部主题不用生效,在默认主题下【白天主题】可以自定义局部主题)
思路:
看到这个,和一键换肤的功能类似,大致思路如下:
- 组件类的采用官方文档的操作方式,实现所有组件更换主题
- 非组件类的采用引入变量的方式实现主题的更更换
- 写出白天,黑夜主题的两个文件,通过动态切换的方式,让两个文件相互替换
- 局部主题的变化通过控制系统主题的切换状态,实现主题的变化
操作:
1、在项目中“项目/src/assets/style/themes/”创建dark.css和light.css两个文件夹,在layout页面实现两个文件替换的代码
<script setup>
import {ref,onMounted,watch} from 'vue'
const currentTheme =localStorage.getItem('theme')||ref('light') //获得持久化的状态
onMounted (()=>{
//<link data-theme=1 rel='stylesheet' href='./src/assets/style/themes/light.css'></link> //目标链接
const link = document.createElement('link');
link.setAttribute('data-theme', 1) //给标签做个标识,方便删除
link.rel = 'stylesheet';
link.href = `./src/assets/style/themes/${currentTheme}.css`; //currentTheme 通过按钮切换获取的状态
document.head.appendChild(link);
})
watch(()=>currentTheme.value,(newVal,oldVal)=>{
const oldLink = document.querySelector(`link[data-theme]`);
if (oldLink) {
oldLink.remove();
}
const newLink = document.createElement('link');
newLink.setAttribute('data-theme', 1)
newLink.rel = 'stylesheet';
newLink.href = `./src/assets/style/themes/${newVal}.css`;
document.head.appendChild(newLink);
})
</script>
2、以light.css为例,dark.css里面的变量名相同
/** 通过:root声明全局变量*/
:root{
--color: #000000;
--BgColor: #ffffff
}
/** 在对应的layout的style里面引入,例如:home{background-color:var(--BgColor)}*/
3、更改组件的主题方法 (官方文档:Ant Design Vue — An enterprise-class UI components based on Ant Design and Vue.js)
<script setup>
import zhCN from 'ant-design-vue/es/locale/zh_CN';
import { theme } from 'ant-design-vue';
import {styleStore} from '@/store/style.js'
const store =styleStore() //里面有个状态变量currentComponentTheme,通过改变项目系统主题状态传递过来
//a-config-provider是ant design vue 的一个标签,通过这个配置,即可实现,白天和黑夜的主题切换
</script>
<template>
<a-config-provider :locale="zhCN" :theme="{
algorithm: store.currentComponentTheme=='light'?theme.defaultAlgorithm:theme.darkAlgorithm
}">
<router-view></router-view>
</a-config-provider>
</template>
<style scoped></style>
4、局部 样式和主题样式的权重问题解决办法
刚开始想着使用权重的优先级解决,考虑一下比较麻烦,灵机一动,为啥不能使用dark,light这样的状态实现局部默认(白天)主题和局部暗黑主题的控制,通过三元表达式实现,就在style里写出暗黑模式下的样式,样式值通过var(--color)灵活获取,这样同样能达到权重效果
<template>
<header :class="currentTheme=='light'?'top-bg':'dark-top-bg'">顶部盒子</header>
</template>
<script setup>
import {ref} from 'vue'
const currentTheme =ref('light') //通过按钮切换值
</script>
<style lang='scss' scoped>
/** 默认主题下,不加最高级权重是为了,可以自定义局部主题,暗黑模式下,不能自定义局部主题*/
.top-bg{
background-color:var(--BgColor) ;
}
.dark-top-bg{
background-color:var(--BgColor) !important ;
}
</style>
结语:
到此项目算是达到需求要求,创作不易,欢迎关注