小工具知识网

当前位置: 首页 > 行业知识 > vue3 中 主题定制

行业知识

vue3 中 主题定制

2026-10-29 16:22:34 来源:互联网转载

vue3 中 主题定制

背景

做多主题定制,黑/��� ,里面还要再分各种颜色,每次进来都要记住上次的主题设置

效果图

一、目录结构

├── generated│   ├── theme  │   │   └── dark-yellow.ts│   │   └── dark-orange.ts│   │   └── light-yellow.ts│   │   └── light-orange.ts│   │   └── theme.enums.ts├── stores │   ├── theme-store.ts  

数据结构

主题

枚举

二、流程

  1. Init的时候,根据 store 中的颜色主题,先做一次匹配,changeTheme
  2. 切换主题的时候,监听绑定的值,做 changeTheme
  3. changeTheme 主要就是读取 文件列表,做匹配,做规则制定,最后使用 document.documentElement.style.setProperty 设置style,根据css 变量做匹配

三、核心实现

  1. init 时,设置已存储的theme
import { setupTheme } from '@/stores/theme-store'const app = createApp(App)initApp(app)const initApp = async (app: App) => {  setupStore(app)  setupRouter(app)  setupLang(app)  setupTheme()  app.mount('#app')}
  1. 读取配置主题文件(匹配到的文件默认是懒加载的,通过动态导入实现eager: true)
const themeFileList: Record = import.meta.glob(  ['@/generated/theme/*.ts', '!@/generated/theme/theme.enums.ts'],  {    import: 'default',    eager: true  })
  1. 根据文件夹匹配出主题key
const themeFileListObject = {}for (const key in themeFileList) {  const filename = key.split('/').pop()?.replace('.ts', '')  if (filename) {    themeFileListObject[filename] = themeFileList[key]  }}
  1. 替换root 样式(根据存储key匹配出当前色值表,format css name,then set style)
const injectRootStyle = (theme: ThemeEnum) => {  const themeObject = themeFileListObject[theme]  for (const key in themeObject) {    const cssVariableName = `--${key.replace(/_/g, '-').toLowerCase()}`    document.documentElement.style.setProperty(cssVariableName, themeObject[key])  }}
  1. Pian 中做数据监听,data change to call changeTheme function.
watch(theme, (nVal) => {      changeTheme(nVal)})// 改变主题const changeTheme = (theme: ThemeEnum) => {  injectRootStyle(theme)}//设置主题const setupTheme = () => {  changeTheme(useThemeStore().theme)}

四、总体代码

import ThemeEnum from '@/generated/theme/theme-enum'import { defineStore } from 'pinia'import { ref, watch } from 'vue'// 读取全部主题配置const themeFileList: Record = import.meta.glob(  ['@/generated/theme/*.ts', '!@/generated/theme/theme.enums.ts'],  {    import: 'default',    eager: true  })// 根据读取的文件路径,生成名称和地址const themeFileListObject = {}for (const key in themeFileList) {  const filename = key.split('/').pop()?.replace('.ts', '')  if (filename) {    themeFileListObject[filename] = themeFileList[key]  }}// 注入根样式const injectRootStyle = (theme: ThemeEnum) => {  const themeObject = themeFileListObject[theme]  for (const key in themeObject) {    const cssVariableName = `--${key.replace(/_/g, '-').toLowerCase()}`    document.documentElement.style.setProperty(cssVariableName, themeObject[key])  }}// 定义一个函数,用于改变主题const changeTheme = (theme: ThemeEnum) => {  // 注入根样式  injectRootStyle(theme)}// 定义一个函数,用于设置主题const setupTheme = () => {  // 改变主题  changeTheme(useThemeStore().theme)}const useThemeStore = defineStore(  'theme',  () => {    const theme = ref(ThemeEnum['light-red'])    watch(theme, (nVal) => {      changeTheme(nVal)    })    return { theme }  },  { persist: true })export { setupTheme, changeTheme, useThemeStore }

五、总结

  1. 我们在切换主题的时候,在组件内其实没有做任何处理,是在pinia 里做的监听
  2. 持久化 这里用到了 persist 插件
  3. 通过向外暴露setupTheme 来实现 修改主题

上一篇:织梦系统采集全攻略,轻松掌握技巧,成为采集高手!

下一篇:伺服服务器错误怎么解决?