Vue3 + Element-plus前端项目-主题切换

简介

现在很多项目都会有一个主题切换,支持客户自定义网站主题。 以下我们通过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...

相关推荐
苦学编程的谢5 分钟前
计算机是如何工作的
服务器·前端·javascript
蓉妹妹19 分钟前
React+Taro选择日期组件封装
前端·react.js·前端框架
风口上的吱吱鼠23 分钟前
记录 ubuntu 安装中文语言出现 software database is broken
linux·服务器·前端
whltaoin30 分钟前
前端弹性布局:用Flexbox构建现代网页的魔法指南
前端·弹性布局
GISer_Jing2 小时前
前端工程化和性能优化问题详解
前端·性能优化
学渣y2 小时前
React文档-State数据扁平化
前端·javascript·react.js
njsgcs2 小时前
画立方体软件开发笔记 js three 投影 参数建模 旋转相机 @tarikjabiri/dxf导出dxf
前端·javascript·笔记
一口一个橘子2 小时前
[ctfshow web入门] web71
前端·web安全·网络安全
逊嘘2 小时前
【Web前端开发】HTML基础
前端·html
未脱发程序员3 小时前
【前端】每日一道面试题3:如何实现一个基于CSS Grid的12列自适应布局?
前端·css