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...

相关推荐
程序员爱钓鱼38 分钟前
Rust 变量与不可变性:为什么默认不能修改变量?
前端·后端·rust
随风一样自由1 小时前
【前端工程化】前端工程化解耦实践:从问题分析到架构重构
前端·重构·架构
vortex51 小时前
Web 渗透测试:未授权与越权漏洞全流程挖掘思路
前端
我有满天星辰2 小时前
【前端模块化】前端模块化演进之路:从脚本堆砌到标准统一
前端
我有满天星辰2 小时前
Vue 3 响应式双雄:ref 与 reactive 完全指南
前端·javascript·vue.js
随风一样自由10 小时前
【前端独角兽】刚进入前端领域的前端开发用jQuery还是Vue3?
前端·javascript·vue3·jquery
IMPYLH11 小时前
HTML 的 <data> 元素
前端·html
YHHLAI11 小时前
[特殊字符] 面试中的 Promise —— 从入门到精通
前端·javascript·面试
leoZ23113 小时前
Claude 驱动的全栈开发:Spring Boot + Vue 的 BS 架构实践
vue.js·spring boot·架构
kyriewen13 小时前
我扒了 GPT-5.6 的全部编程跑分——有一项 OpenAI 没敢放出来
前端·gpt·ai编程