vue3 + Element Plus 系统主题切换

创建主题管理模块(用于配置颜色变量)

新建 src/utils/theme.ts

import { ref, watchEffect } from 'vue'

type ThemeType = 'light' | 'dark' | 'system'

// 主题配置
const themeConfig = {
  light: {
    '--el-color-primary': '#409eff',
    '--bg-color': '#ffffff',
    '--text-color': '#303133'
  },
  dark: {
    '--el-color-primary': '#79bbff',
    '--bg-color': '#141414',
    '--text-color': '#e5eaf3'
  }
}

// 状态管理
const theme = ref(localStorage.getItem('theme') as ThemeType || 'light')

// 监听系统主题变化
const systemThemeMatch = window.matchMedia('(prefers-color-scheme: dark)')

// 获取当前生效主题
const getRealTheme = () => {
  if (theme.value === 'system') {
    return systemThemeMatch.matches ? 'dark' : 'light'
  }
  return theme.value
}

// 应用主题
const applyTheme = (themeType: 'light' | 'dark') => {
  const variables = themeConfig[themeType]
  Object.entries(variables).forEach(([key, value]) => {
    document.documentElement.style.setProperty(key, value)
  })
  document.documentElement.className = themeType
}

// 初始化监听
const initThemeListener = () => {
  systemThemeMatch.addEventListener('change', () => {
    if (theme.value === 'system') {
      applyTheme(getRealTheme())
    }
  })
}

// 切换主题
const toggleTheme = (newTheme: ThemeType) => {
  theme.value = newTheme
  localStorage.setItem('theme', newTheme)
  applyTheme(getRealTheme())
}

export function useTheme() {
  return {
    theme,
    toggleTheme,
    initThemeListener
  }
}
全局样式配置

新建 src/styles/theme.scss

:root {
  // 默认亮色主题变量
  @each $name, $color in $light-theme {
    --#{$name}: #{$color};
  }
  
  // 动态背景色和文字颜色
  background-color: var(--bg-color);
  color: var(--text-color);
  
  // Element Plus组件样式覆盖
  .el-button {
    background-color: var(--bg-color);
    color: var(--text-color);
  }
  
  // 添加其他需要自定义的组件样式...
}

主题切换组件

新建 src/components/ThemeSwitch.vue




初始化配置

在 main.ts 中添加:

import { createApp } from 'vue'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import { useTheme } from './utils/theme'

const app = createApp(App)

// 初始化主题
const { initThemeListener, applyTheme, getRealTheme } = useTheme()
app.use(ElementPlus, {
  zIndex: 3000,
  size: 'default',
  theme: getRealTheme()
})
applyTheme(getRealTheme())
initThemeListener()

app.mount('#app')

核心实现原理
CSS变量控制:通过修改documentElement的CSS Variables实现动态换肤
响应式存储:使用localStorage保存用户选择,结合Vue3的响应式系统
系统主题监听:通过window.matchMedia检测系统主题变化
Element Plus整合:根据主题动态设置Element组件库的基础配置

vue3 + Element Plus 系统主题切换_第1张图片 

你可能感兴趣的:(vue.js,前端,javascript)