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";`
      }
    }
  }
});
相关推荐
鼎道开发者联盟5 分钟前
鼎享会 | OpenClaw Control UI 前端架构全解析:自研 UI 对接 Server 实操指南
前端·ui·架构·openclaw·control ui
尘世中一位迷途小书童7 分钟前
一套完整的给予ceium封装的组件库,可满足企业级开发
前端
Z_Wonderful8 分钟前
微前端:Webpack 配置 vs Vite 配置 超清晰对比
前端·webpack·node.js
码云数智-园园13 分钟前
HTTPS是如何工作的?从HTTP到HTTPS的加密演进
前端
隔窗听雨眠21 分钟前
HTML头部元信息避坑指南
前端·html
Gauss松鼠会29 分钟前
【openGauss】openGauss 磁盘引擎之 ustore
java·服务器·开发语言·前端·数据库·经验分享·gaussdb
LIO30 分钟前
前端响应式页面开发全攻略:核心技术 + 实现效果 + 实战指南
前端·响应式设计
许彰午38 分钟前
Spring Boot + Vue 实现 XML 动态表单:固定字段 + 自由扩展方案
xml·vue.js·spring boot
得物技术1 小时前
AI驱动:从运营行为到自动化用例的智能化实践|得物技术
前端·ai编程·全栈
前端那点事1 小时前
Vue并发控制|几十个请求高效管控(实战方案+可运行代码)
前端·vue.js