Vue 3+Vite+TypeScript项目中使用Element Plus实现主题切换(明亮主题、暗黑主题、蓝色主题)

一、

首先,在CSS中定义两种主题(亮色和暗色)的样式,并使用CSS变量来控制颜色。

css 复制代码
/* base.css */  
:root {  
    --bg-color: #ffffff; /* 背景颜色,默认为白色 */  
    --text-color: #000000; /* 文本颜色,默认为黑色 */  
    --link-color: #0000ee; /* 链接颜色 */  
    --button-bg-color: #f0f0f0; /* 按钮背景颜色 */  
    --button-text-color: #000000; /* 按钮文本颜色 */  
}  
  
body {  
    background-color: var(--bg-color);  
    color: var(--text-color);  
    transition: background-color 0.3s, color 0.3s;  
}  
  
a {  
    color: var(--link-color);  
}  
  
button {  
    background-color: var(--button-bg-color);  
    color: var(--button-text-color);  
    border: none;  
    padding: 10px 20px;  
    cursor: pointer;  
    transition: background-color 0.3s, color 0.3s;  
}  
  
/* 暗黑模式样式 */  
body.dark-mode {  
    --bg-color: #333333;  
    --text-color: #ffffff;  
    --link-color: #00eeff;  
    --button-bg-color: #444444;  
    --button-text-color: #ffffff;  
}

二、

确保你已经安装了Element Plus和相关依赖

css 复制代码
npm install element-plus
npm install @vueuse/core

在你的`main.ts`文件中引入Element Plus和相关样式

javascript 复制代码
import { createApp } from 'vue';
import App from './App.vue';
import ElementPlus from 'element-plus';
import 'element-plus/theme-chalk/dark/css-vars.css';
import './styles/index.css'; // 用于自定义主题的样式

const app = createApp(App);

app.use(ElementPlus);

app.mount('#app');

在`src`目录下创建一个`theme.ts`文件,用于管理主题切换的逻辑

javascript 复制代码
import { ref } from 'vue';
import { usePreferredDark } from '@vueuse/core';

const isDark = ref(usePreferredDark());

export function useTheme() {
  const toggleTheme = (theme: 'light' | 'dark' | 'blue') => {
    const classList = document.documentElement.classList;
    if (theme === 'light') {
      classList.remove('dark');
      classList.remove('blue');
    } else if (theme === 'dark') {
      classList.add('dark');
      classList.remove('blue');
    } else if (theme === 'blue') {
      classList.add('blue');
      classList.remove('dark');
    }
  };

  return { isDark, toggleTheme };
}

在`src/styles`目录下创建一个`index.css`文件,并定义你的主题样式

css 复制代码
/* index.css */

/* 全局基础样式 */
html {
  --el-color-primary: #409eff; /* 默认主题色 */
  --el-color-success: #67c23a;
  --el-color-warning: #e6a23c;
  --el-color-danger: #f56c6c;
  --el-color-info: #909399;

  --el-border-radius-base: 4px;
  --el-border-color-base: #dcdfe6;
}

/* 暗黑主题样式 */
html.dark {
  --el-color-primary: #1f1f1f; /* 暗黑主题色 */
  --el-color-success: #67c23a;
  --el-color-warning: #e6a23c;
  --el-color-danger: #f56c6c;
  --el-color-info: #909399;

  --el-border-radius-base: 4px;
  --el-border-color-base: #303133;

  --el-bg-color: #1f1f1f; /* 背景色 */
  --el-text-color-primary: #ffffff; /* 主要文本色 */
  --el-text-color-regular: #dcdfe6; /* 常规文本色 */
  --el-text-color-placeholder: #909399; /* 占位符色 */
}

/* 蓝色主题样式 */
html.blue {
  --el-color-primary: #1e90ff; /* 蓝色主题色 */
  --el-color-success: #67c23a;
  --el-color-warning: #e6a23c;
  --el-color-danger: #f56c6c;
  --el-color-info: #909399;

  --el-border-radius-base: 4px;
  --el-border-color-base: #dcdfe6;
}

/* 覆盖Element Plus组件样式 */
.el-button {
  border-radius: var(--el-border-radius-base);
  background-color: var(--el-color-primary);
  color: #fff;
}

.el-button--primary {
  background-color: var(--el-color-primary);
  border-color: var(--el-color-primary);
}

.el-button--success {
  background-color: var(--el-color-success);
  border-color: var(--el-color-success);
}

.el-button--warning {
  background-color: var(--el-color-warning);
  border-color: var(--el-color-warning);
}

.el-button--danger {
  background-color: var(--el-color-danger);
  border-color: var(--el-color-danger);
}

.el-button--info {
  background-color: var(--el-color-info);
  border-color: var(--el-color-info);
}

.el-input__inner {
  border-color: var(--el-border-color-base);
  background-color: var(--el-bg-color);
  color: var(--el-text-color-primary);
}

.el-input__placeholder {
  color: var(--el-text-color-placeholder);
}

.el-table th,
.el-table td {
  border-color: var(--el-border-color-base);
  color: var(--el-text-color-primary);
  background-color: var(--el-bg-color);
}

.el-menu {
  background-color: var(--el-bg-color);
  color: var(--el-text-color-regular);
}

.el-menu-item.is-active {
  background-color: var(--el-color-primary);
  color: #fff;
}

/* 根据主题调整其他组件样式 */
.el-header,
.el-footer {
  background-color: var(--el-bg-color);
  color: var(--el-text-color-primary);
}

.el-main {
  background-color: var(--el-bg-color);
}

.el-pagination__total,
.el-pagination__sizes,
.el-pagination__prev,
.el-pagination__pager,
.el-pagination__next,
.el-pagination__jump {
  color: var(--el-text-color-primary);
}

创建一个`ThemeSwitcher.vue`组件,用于切换主题

html 复制代码
<template>
  <div>
    <el-select v-model="selectedTheme" placeholder="Select Theme" @change="onThemeChange">
      <el-option label="Light" value="light"></el-option>
      <el-option label="Dark" value="dark"></el-option>
      <el-option label="Blue" value="blue"></el-option>
    </el-select>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue';
import { useTheme } from '@/theme';

export default defineComponent({
  setup() {
    const { toggleTheme } = useTheme();
    const selectedTheme = ref<'light' | 'dark' | 'blue'>('light');

    const onThemeChange = (theme: 'light' | 'dark' | 'blue') => {
      toggleTheme(theme);
    };

    return {
      selectedTheme,
      onThemeChange,
    };
  },
});
</script>

<style scoped>
/* 可添加本地样式 */
</style>

在App.vue中使用主题切换组件

html 复制代码
<template>
  <div id="app">
    <theme-switcher />
    <router-view />
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import ThemeSwitcher from './components/ThemeSwitcher.vue';

export default defineComponent({
  components: {
    ThemeSwitcher,
  },
});
</script>

确保在`vite.config.ts`中包含以下配置,以支持CSS变量和预处理:

javascript 复制代码
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
  plugins: [vue()],
  css: {
    preprocessorOptions: {
      scss: {
        additionalData: `@import "./src/styles/variables.scss";`
      }
    }
  }
});
相关推荐
技术钱1 小时前
vue3 封装图片上传预览组件支持docx、excel、pdf、图片、txt格式
vue.js·pdf·excel
kyle~1 小时前
C++--- override 关键字 强制编译器验证当前函数是否重写基类的虚函数
java·前端·c++
Light601 小时前
像素退场,曲线登场:现代响应式 CSS 全家桶 | 领码课堂
前端·css·响应式设计·css函数·布局系统·相对单位·设计令牌
爱生活的苏苏2 小时前
elementUI 表单验证-联动型校验
前端·javascript·elementui
一只小风华~4 小时前
Vue Router 路由元信息(meta)详解
前端·javascript·vue.js
*且听风吟4 小时前
html 实现鼠标滑动点亮横轴
前端·javascript·html
计算机学姐4 小时前
基于微信小程序的垃圾分类管理系统【2026最新】
java·vue.js·spring boot·mysql·微信小程序·小程序·mybatis
武昌库里写JAVA6 小时前
C语言 #pragma once - C语言零基础入门教程
vue.js·spring boot·sql·layui·课程设计
iCoding916 小时前
前端分页 vs 后端分页:技术选型
前端·后端·系统架构
mingtianyihou336 小时前
使用 Service Worker 限制请求并发数
前端