当前位置: 首页 > news >正文

vue3 中 主题定制

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<string, string> = 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<string, string> = 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 来实现 修改主题
http://www.lryc.cn/news/309141.html

相关文章:

  • 数据分析之Logistic回归分析(二元逻辑回归、多元有序逻辑回归、多元无序逻辑回归)
  • 【c++】通讯录管理系统
  • Tomcat 架构
  • Spring 整合mybatis
  • centos7升级openssl_3
  • nvidia a100-pcie-40gb环境安装
  • 嵌入式 Linux 下的 LVGL 移植
  • js同步和异步请求
  • 【Leetcode】2369. 检查数组是否存在有效划分
  • Laravel Octane 和 Swoole 协程的使用分析
  • 腾讯云又双叕降价,云服务器配置优惠价格表2024新版报价
  • 【react native】css踩坑记录
  • ChatGPT学习第四周
  • 2D割草/吸血鬼游戏 性能优化——GPU Spine动画
  • VSCode上搭建C/C++开发环境(vscode配置c/c++环境)Windows系统---保姆级教程
  • [渗透教程]-013-嗅探工具-wireshark操作
  • NLP Seq2Seq模型
  • 如何在 Linux 上使用 dmesg 命令
  • WPF的DataGrid设置标题头
  • 【软考】UML中的图之通信图
  • 为什么ChatGPT预训练能非常好地捕捉语言的普遍特征和模式
  • 如何安装ProtoBuf环境
  • C语言 vs Rust应该学习哪个?
  • IT廉连看——Uniapp——配置文件pages
  • 服务器上部署WEb服务方法
  • 设计模式:模版模式
  • pikachu之特殊注入之搜索型注入、xx型注入、insert/update注入、delete注入、宽字节注入
  • docker构建hyperf环境
  • WPF常用mvvm开源框架介绍 vue的mvvm设计模式鼻祖
  • HTML <script>元素的10个属性