前端实现主题切换,代码量最小的解决方法!

本文介绍了一种在Vue项目中实现主题切换的简洁方法,通过CSS变量和`:root`选择器,配合ElementPlus组件,即使在大型项目中也能轻松完成。文章详细阐述了操作步骤和如何在Vue3中使用Pinia进行状态管理,确保主题切换的持久性。
摘要由CSDN通过智能技术生成

前端实现主题切换,代码量最小的解决方法!

实现功能

之前有一个项目的UI界面进行了更新,产品提了一个需求:现在的项目的ui有部分用户觉得不好看,但是有另外一部分用户觉得以前的版本好看,是否可以实现一个功能做实现主题切换。因为这个项目代码量比较多,参与的人也很多,每个人代码风格也不一样,当时就给产品说做不了,这两天空了之后研究了一下,找了很多方案,整理了一下个人认为最简单的方案,点击切换主题不仅能更改自定义的样式,还可以修改ellementplus的组件样式,以下是完成的效果

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

项目简述

gitee地址:https://gitee.com/lyh509/white-v3-template
构建工具:vite
UI库:ElementPlus
代码规范工具:Eslint + Prettier + Husky
预编译器:scss
css库:tailwindCss
路由:vue-router
状态管理:Pinia

当然如果你的项目是使用vue2或者其他框架,也没有影响,大体的思路是一样的

操作步骤

1.首先按照下图创建styles文件夹及文件夹下的index.scss和theme.css

在这里插入图片描述

index.scss代码如下:


.bg-color {
  background: var(--bg-color);
}
.text-clor {
  color: var(--text-color);
}

theme.css代码如下:

:root[theme=‘xxxx’](:root表示根节点选择器,:root[theme=‘xxxx’]表示在根节点的theme属性为xxxx时样式为以下代码)

主题切换原理就是更改根节点的theme属性,来切换样式

/* 更改element的组件样式 */
:root {
  --el-menu-text-color: var(--text-color);
  --el-menu-bg-color: var(--bg-color);
  --el-menu-border-color: var(--bg-color);
}

/* 主题一 */
:root[theme='theme_1'] {
  --bg-color: #0d1117;
  --text-color: #3498db;
}

/* 主题二 */
:root[theme='theme_2'] {
  --bg-color: #b74141;
  --text-color: #fff;
}

/* 主题三 */
:root[theme='theme_3'] {
  --bg-color: #f1c40f;
  --text-color: #c0392b;
}

如果想要修改element组件样式,找到想要修改颜色的element组件,打开控制台审查元素,找到要修改的颜色属性,将var()括号中的样式变量名称复制到theme.css中如上图第一个模块,将颜色更改为我们主题颜色变量名称(我们这里是以修改el-menu背景颜色为例)

在这里插入图片描述

2.然后在main.ts中引入

//main.ts
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
import '@/styles/theme.css'
import '@/styles/index.scss'
app.mount('#app')

3.设置class到需要应用到的组件

图片左侧的TopBar是页面的头部组件,我们在index.scss中定义了bg-color和text-color两个类名,接下来我们将这两个类名加到topBar组件的对应位置

在这里插入图片描述

代码截图:

在这里插入图片描述

4.实现主题切换

普通方法

在要切换组件的按钮或者下拉框组件上绑定changeTheme方法(我这里是用的下拉框来触发主题切换事件),在changeTheme方法里使用document.documentElement获取到页面dom的根节点,并且在该节点上设置一个名为theme的属性,当根节点属性值发生变化时,页面的颜色参数值也会改变(这个地方可以看一看上面的theme.css代码)

在这里插入图片描述

TopBar.vue代码:

<template>
  <div class="w-full h-10 flex justify-between items-center bg-color">
    <span class="text-clor font-bold w-full h-full">Vue3 框架模板</span>
    <section class="flex items-center justify-end h-full">
      <el-button @click="logout">注销</el-button>
      <el-select
        v-model="value"
        placeholder="Select"
        style="width: 240px"
        @change="changeTheme"
      >
        <el-option
          v-for="item in options"
          :key="item.value"
          :label="item.label"
          :value="item.value"
          :disabled="item.disabled"
        />
      </el-select>
    </section>
  </div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue'
import useCounter from '@/store/user'
import { defineProps } from 'vue'
export default defineComponent({
  setup() {
    const user = useCounter()
    const value = ref(user.theme)
    defineProps(['userInfo'])
    const options = [
      {
        label: '主题1',
        value: 'theme_1',
        disabled: false,
      },
      {
        label: '主题2',
        value: 'theme_2',
        disabled: false,
      },
      {
        label: '主题3',
        value: 'theme_3',
        disabled: false,
      },
    ]
    /************************核心代码****************************/
    const changeTheme = (val) => {
        document.documentElement.setAttribute('theme', val)
    }
    //因为页面首次进入或者dom重新渲染时,dom根节点上没有设置theme,所以在这里先调用一次changeTheme方法,设置初始主题
    changeTheme(options[0].value)
    /****************************************************/  
    const logout = () => {
      user.setIsLogin(false)
    }
    return { user, value, options, logout }
  },
})
</script>
<style lang="scss" scoped></style>
小优化

在这里插入图片描述

上面那种方法可以简单的实现主题切换,但是如果我们刷新浏览器后,系统的主题又会被重置,而在现实情况下,当用户切换主题颜色后,刷新页面应该不会重置主题,所以我这里是把更改dom根节点theme属性值的操作放到了pinia中的actions操作,然后在下拉框事件中调用actions中的serTheme方法,并且对状态管理器做了持久化操作

  • 22
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值