简介
现在很多项目都会有一个主题切换,支持客户自定义网站主题。 以下我们通过css变量来完成对一个完整的项目支持主题切换的实践 预览链接 lancejiang.github.io/Lance-Eleme...
1. 配置主题
定义默认主题
ts
// settings.ts
export const defaultSettingState = {
/** 主题模式 */
// 主题颜色
themeColor: '#409eff',
// 暗黑主题
isDark: false,
}
配置主题相关的store
ts
// modules/settings
// 定义主题配置store
import defaultSettings from 'settings.ts'
import { defineStore } from 'pinia'
export const useSettingStore = defineStore({
id: 'setting',
state: (): SettingState => defaultSettings,
actions: {
async changeSetting(...payload: [string, any]) {
const [key, value] = payload
this[key] = value
}
}
})
export default useSettingStore
2. 主题hooks 逻辑
颜色切换工具函数
ts
// utils/color.ts
/**
* @description hex颜色转rgb颜色
* @param {String} str 颜色值字符串
* @returns {String} 返回处理后的颜色值
*/
export function hexToRgb(str: any) {
let hexs: any = ''
const reg = /^\#?[0-9A-Fa-f]{6}$/
if (!reg.test(str)) return ''
str = str.replace('#', '')
hexs = str.match(/../g)
for (let i = 0; i < 3; i++) hexs[i] = parseInt(hexs[i], 16)
return hexs
}
/**
* @description rgb颜色转Hex颜色
* @param {*} r 代表红色
* @param {*} g 代表绿色
* @param {*} b 代表蓝色
* @returns {String} 返回处理后的颜色值
*/
export function rgbToHex(r: any, g: any, b: any) {
const reg = /^\d{1,3}$/
if (!reg.test(r) || !reg.test(g) || !reg.test(b)) return ''
const hexs = [r.toString(16), g.toString(16), b.toString(16)]
for (let i = 0; i < 3; i++) if (hexs[i].length == 1) hexs[i] = `0${hexs[i]}`
return `#${hexs.join('')}`
}
/**
* @description 加深颜色值
* @param {String} color 颜色值字符串
* @param {Number} level 加深的程度,限0-1之间
* @returns {String} 返回处理后的颜色值
*/
export function getDarkColor(color: string, level: number) {
const reg = /^\#?[0-9A-Fa-f]{6}$/
if (!reg.test(color)) return ''
const rgb = hexToRgb(color)
for (let i = 0; i < 3; i++) rgb[i] = Math.round(20.5 * level + rgb[i] * (1 - level))
return rgbToHex(rgb[0], rgb[1], rgb[2])
}
/**
* @description 变浅颜色值
* @param {String} color 颜色值字符串
* @param {Number} level 加深的程度,限0-1之间
* @returns {String} 返回处理后的颜色值
*/
export function getLightColor(color: string, level: number) {
const reg = /^\#?[0-9A-Fa-f]{6}$/
if (!reg.test(color)) return ''
const rgb = hexToRgb(color)
for (let i = 0; i < 3; i++) rgb[i] = Math.round(255 * level + rgb[i] * (1 - level))
return rgbToHex(rgb[0], rgb[1], rgb[2])
}
定义主题hooks useTheme
ts
import useSettingStore from './modules/settings'
import { getLightColor, getDarkColor } from './utils/color'
import { storeToRefs } from 'pinia'
export const useTheme = () => {
const setting = useSettingStore()
const { themeColor, isDark } = storeToRefs(setting)
// 暗黑模式切换
const switchDark = () => {
const html = document.documentElement as HTMLElement
html.setAttribute('class', isDark.value ? 'dark' : '')
changeThemeColor(themeColor.value)
}
// 修改主题颜色
const changeThemeColor = (val: string) => {
// 计算主题颜色变化
document.documentElement.style.setProperty('--el-color-primary', val)
// 颜色加深 :active 触发
document.documentElement.style.setProperty('--el-color-primary-dark-2', isDark.value ? `${getLightColor(val, 0.2)}` : `${getDarkColor(val, 0.3)}`)
for (let i = 1; i < 10; i++) {
const primaryColor = isDark.value ? `${getDarkColor(val, i / 10)}` : `${getLightColor(val, i / 10)}`
document.documentElement.style.setProperty(`--el-color-primary-light-${i}`, primaryColor)
}
setting.changeSetting('themeColor', val)
}
// init theme
const initTheme = () => {
switchDark()
}
return {
initTheme,
switchDark,
changeThemeColor
}
}
3. 项目植入
项目初始化
ts
// App.vue script 部分
<script setup lang="ts">
import { useTheme } from './hooks/useTheme'
// 初始化 主题
const { initTheme } = useTheme()
initTheme()
</script>
主题/主题色切换
html
<!-- setting.vue template 部分-->
<div>
<div class="drawer-title">设置</div>
<div class="drawer-wrap">
<div class="drawer-item">
<span>主题颜色</span>
<el-color-picker :model-value="themeColor" @update:model-value="changeThemeColor" />
</div>
<div class="drawer-item">
<span>暗黑主题</span>
<el-switch v-model="isDark" inline-prompt active-icon="Sunny" inactive-icon="Moon" @change="switchDark" />
</div>
</div>
</div>
ts
// setting.vue script 部分
import { storeToRefs } from 'pinia'
<script setup lang="ts">
import { storeToRefs } from 'pinia'
import { useTheme } from '@/hooks/useTheme'
import useSettingStore from './modules/settings'
const setting = useSettingStore()
const { switchDark, changeThemeColor } = useTheme()
const { isDark, themeColor } = storeToRefs(setting)
</script>
以上就是项目 完整的 主题切换的功能啦
✿✿ヽ(°▽°)ノ✿
项目可能还含有 水印
布局切换
都可以在 setting.vue
文件中做扩展 完整的项目看下面喔
结束
分享给大家一个Vue3 + Ts + Element-plus & Vite
搭建,开箱即用的后台管理项目, 手机端已兼容,如果觉得不错希望可以得到各位大佬的star
项目链接 github.com/LanceJiang/...
访问链接 lancejiang.github.io/Lance-Eleme...