vue3+TS 整合element-plus和tailwindcss
1. 安装依赖
npminstallelement-plus @element-plus/icons-vue @vueuse/corenpminstall-Dtailwindcss @tailwindcss/vite sass2. Vite 配置
vite.config.ts
import{defineConfig}from'vite'importvuefrom'@vitejs/plugin-vue'importtailwindcssfrom'@tailwindcss/vite'exportdefaultdefineConfig({plugins:[vue(),tailwindcss(),],})3. 全局样式文件
src/style.css
/* 使用 @tailwindcss/vite 方式导入 */@import"tailwindcss";/* 配置暗色模式 */@custom-variantdark(&:where(.dark,.dark *));/* 全局过渡动画 */*{transition:background-color 0.3s ease,color 0.3s ease,border-color 0.3s ease;}/* 滚动条样式 */::-webkit-scrollbar{width:8px;height:8px;}::-webkit-scrollbar-track{background:#f1f1f1;}.dark ::-webkit-scrollbar-track{background:#2a2a2a;}::-webkit-scrollbar-thumb{background:#888;border-radius:4px;}.dark ::-webkit-scrollbar-thumb{background:#555;}::-webkit-scrollbar-thumb:hover{background:#555;}.dark ::-webkit-scrollbar-thumb:hover{background:#666;}4. 主题 Composable
src/composables/useTheme.ts
import{useDark,useToggle,usePreferredDark}from'@vueuse/core'import{computed,watch,typeRef}from'vue'typeThemeMode='light'|'dark'|'auto'interfaceUseThemeReturn{isDark:Ref<boolean>themeMode:Ref<ThemeMode>toggleTheme:()=>voidsetThemeMode:(mode:ThemeMode)=>void}exportfunctionuseTheme():UseThemeReturn{constpreferredDark=usePreferredDark()constisDark=useDark({storageKey:'theme-mode',valueDark:'dark',valueLight:'light',})constthemeMode=computed<ThemeMode>({get:()=>{constsaved=localStorage.getItem('theme-mode')asThemeMode|nullif(saved==='light'||saved==='dark'){returnsaved}return'auto'},set:(mode:ThemeMode)=>{if(mode==='auto'){localStorage.removeItem('theme-mode')isDark.value=preferredDark.value}else{localStorage.setItem('theme-mode',mode)isDark.value=mode==='dark'}}})consttoggleTheme=useToggle(isDark)constsetThemeMode=(mode:ThemeMode):void=>{themeMode.value=mode}watch(preferredDark,(newVal)=>{if(themeMode.value==='auto'){isDark.value=newVal}})return{isDark,themeMode,toggleTheme,setThemeMode,}}5. Element Plus 暗色主题配置
src/styles/element-dark.scss
// Element Plus 暗色主题自定义 html.dark { --el-bg-color: #1a1a1a; --el-bg-color-overlay: #1d1d1d; --el-text-color-primary: #e5e5e5; --el-text-color-regular: #cfcfcf; --el-border-color: #4c4d4f; --el-fill-color: #2a2a2a; --el-fill-color-light: #333333; --el-fill-color-lighter: #3a3a3a; --el-fill-color-extra-light: #404040; --el-box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.3); }6. 主题切换组件
src/components/ThemeToggle.vue
<template> <el-switch v-model="isDark" :active-icon="Moon" :inactive-icon="Sunny" @change="toggleTheme" class="theme-switch" /> </template> <script setup lang="ts"> import { computed } from 'vue' import { Moon, Sunny } from '@element-plus/icons-vue' import { useTheme } from '@/composables/useTheme' const { isDark, toggleTheme } = useTheme() </script> <style scoped> .theme-switch { --el-switch-off-color: #409eff; --el-switch-on-color: #303030; } </style>7. 主题选择器组件(下拉菜单)
src/components/ThemeSelector.vue
<template> <el-dropdown @command="handleCommand"> <div class="flex items-center cursor-pointer p-2 hover:bg-gray-200 dark:hover:bg-gray-700 rounded-lg"> <el-icon :size="20"> <component :is="currentIcon" /> </el-icon> <span class="ml-2 text-sm hidden sm:inline"> {{ currentTheme === 'dark' ? '暗色' : '亮色' }} </span> </div> <template #dropdown> <el-dropdown-menu> <el-dropdown-item command="light"> <el-icon><Sunny /></el-icon> <span class="ml-2">亮色</span> </el-dropdown-item> <el-dropdown-item command="dark"> <el-icon><Moon /></el-icon> <span class="ml-2">暗色</span> </el-dropdown-item> <el-dropdown-item command="auto"> <el-icon><Monitor /></el-icon> <span class="ml-2">跟随系统</span> </el-dropdown-item> </el-dropdown-menu> </template> </el-dropdown> </template> <script setup lang="ts"> import { computed } from 'vue' import { Sunny, Moon, Monitor } from '@element-plus/icons-vue' import { useTheme } from '@/composables/useTheme' const { isDark, themeMode, setThemeMode } = useTheme() const currentIcon = computed(() => { if (themeMode.value === 'auto') return Monitor return isDark.value ? Moon : Sunny }) const currentTheme = computed(() => { if (themeMode.value === 'auto') return 'auto' return isDark.value ? 'dark' : 'light' }) const handleCommand = (command: 'light' | 'dark' | 'auto'): void => { setThemeMode(command) } </script>8. 主应用文件
src/App.vue
<template> <div class="min-h-screen bg-white dark:bg-gray-900 transition-colors duration-300"> <!-- 顶部导航栏 --> <header class="bg-gray-100 dark:bg-gray-800 shadow-md p-4 transition-colors duration-300"> <div class="container mx-auto flex justify-between items-center"> <h1 class="text-2xl font-bold text-gray-800 dark:text-white"> Vue3 + Element Plus + Tailwind </h1> <div class="flex items-center gap-4"> <ThemeSelector /> <ThemeToggle /> </div> </div> </header> <!-- 主内容 --> <main class="container mx-auto p-6"> <el-card class="mb-4"> <template #header> <span class="text-gray-800 dark:text-white">Element Plus 组件示例</span> </template> <div class="space-y-4"> <el-button type="primary">主要按钮</el-button> <el-button type="success">成功按钮</el-button> <el-button type="warning">警告按钮</el-button> <el-button type="danger">危险按钮</el-button> <el-button type="info">信息按钮</el-button> </div> </el-card> <!-- 使用 Tailwind 的暗色样式 --> <div class="grid grid-cols-1 md:grid-cols-3 gap-4"> <div v-for="i in 3" :key="i" class="p-6 bg-white dark:bg-gray-800 rounded-lg shadow-md border border-gray-200 dark:border-gray-700 text-gray-800 dark:text-white transition-colors duration-300" > <h3 class="text-lg font-semibold mb-2">卡片 {{ i }}</h3> <p class="text-gray-600 dark:text-gray-300"> 这是一个使用 Tailwind CSS 实现的暗色模式卡片 </p> </div> </div> </main> </div> </template> <script setup lang="ts"> import ThemeToggle from './components/ThemeToggle.vue' import ThemeSelector from './components/ThemeSelector.vue' </script>9. 主入口文件
src/main.ts
import{createApp}from'vue'importElementPlusfrom'element-plus'import'element-plus/dist/index.css'import'element-plus/theme-chalk/dark/css-vars.css'import'./styles/element-dark.scss'import'./style.css'importAppfrom'./App.vue'constapp=createApp(App)app.use(ElementPlus)app.mount('#app')10. 最终效果
亮色
暗色