vue3 中 主题定制
vue3 中 主题定制
背景
做多主题定制,黑/白 ,里面还要再分各种颜色,每次进来都要记住上次的主题设置
效果图

一、目录结构
├── generated
│ ├── theme
│ │ └── dark-yellow.ts
│ │ └── dark-orange.ts
│ │ └── light-yellow.ts
│ │ └── light-orange.ts
│ │ └── theme.enums.ts
├── stores
│ ├── theme-store.ts
数据结构
主题

枚举

二、流程
- Init的时候,根据 store 中的颜色主题,先做一次匹配,changeTheme
- 切换主题的时候,监听绑定的值,做 changeTheme
- changeTheme 主要就是读取 文件列表,做匹配,做规则制定,最后使用
document.documentElement.style.setProperty设置style,根据css 变量做匹配
三、核心实现
- 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')
}
- 读取配置主题文件(匹配到的文件默认是懒加载的,通过动态导入实现eager: true)
const themeFileList: Record<string, string> = import.meta.glob(['@/generated/theme/*.ts', '!@/generated/theme/theme.enums.ts'],{import: 'default',eager: true}
)

- 根据文件夹匹配出主题key
const themeFileListObject = {}
for (const key in themeFileList) {const filename = key.split('/').pop()?.replace('.ts', '')if (filename) {themeFileListObject[filename] = themeFileList[key]}
}

- 替换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])}
}

- 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 }
五、总结
- 我们在切换主题的时候,在组件内其实没有做任何处理,是在pinia 里做的监听
- 持久化 这里用到了 persist 插件
- 通过向外暴露setupTheme 来实现 修改主题
相关文章:
vue3 中 主题定制
vue3 中 主题定制 背景 做多主题定制,黑/白 ,里面还要再分各种颜色,每次进来都要记住上次的主题设置 效果图 一、目录结构 ├── generated │ ├── theme │ │ └── dark-yellow.ts │ │ └── dark-orange.ts │ │…...
数据分析之Logistic回归分析(二元逻辑回归、多元有序逻辑回归、多元无序逻辑回归)
1、Logistic回归分类 在研究X对于Y的影响时: 如果Y为定量数据,那么使用多元线性回归分析;如果Y为定类数据,那么使用Logistic回归分析。 结合实际情况,可以将Logistic回归分析分为3类: 二元Logistic回归…...
【c++】通讯录管理系统
1.系统功能介绍及展示 2.创建项目 3.菜单实现 4.退出功能实现 5.添加联系人—结构体设计 6.添加联系人—功能实现 7.显示联系人 8.删除练习人—检测联系人是否存在 9.删除联系人—功能实现 10.查找联系人 11.修改联系人 12.清空通讯录 #include <iostream> #include <…...
Tomcat 架构
一、Http工作原理 HTTP协议是浏览器与服务器之间的数据传送协议。作为应用层协议,HTTP是基于TCP/IP协议来传递数据的(HTML文件、图片、查询结果等),HTTP协议不涉及数据包(Packet)传输,主要规定了…...
Spring 整合mybatis
目录 1、梳理整合思路 2、整合实现 2.1 环境搭建 2.2 案例 1、梳理整合思路 将MyBatis的DataSource交给Spring IoC容器创建并管理,使用第三方数据库连接池(Druid,C3P0等)代替MyBatis内置的数据库连接池将MyBatis的SqlSessionFactory交给Spring IoC容…...
centos7升级openssl_3
1、查看当前openssl版本 openssl version #一般都是1.几的版本2、下载openssl_3的包 wget --no-check-certificate https://www.openssl.org/source/old/3.0/openssl-3.0.3.tar.gz#解压 tar zxf openssl-3.0.3.tar.gz#进入指定的目录 cd openssl-3.0.33、编译安装遇到问题缺…...
nvidia a100-pcie-40gb环境安装
1.conda create --name torch_li python3.8 2. conda install pytorch1.7.1 torchvision0.8.2 torchaudio0.7.2 cudatoolkit11.0 -c pytorch 环境测试:torch.cuda.is_available() 3.conda remove -n torch_li --all 4.pip install opencv-python-headless 5.pip ins…...
嵌入式 Linux 下的 LVGL 移植
目录 准备创建工程修改配置修改 lv_drv_conf.h修改 lv_conf.h修改 main.c修改 Makefile 编译运行更多内容 LVGL(Light and Versatile Graphics Library)是一个轻量化的、开源的、在嵌入式系统中广泛使用的图形库,它提供了一套丰富的控件和组件…...
js同步和异步请求
2023.3.2今天我学习了同步请求和异步请求的区别: 同步请求: 指代码按照顺序依次执行,每一行代码都要等待上一行代码执行完成后才能继续执行,比如你有两个接口,它会第一个接口请求完才去请求下一个接口。 异步请求&a…...
【Leetcode】2369. 检查数组是否存在有效划分
文章目录 题目思路代码结果 题目 题目链接 给你一个下标从 0 开始的整数数组 nums ,你必须将数组划分为一个或多个 连续 子数组。 如果获得的这些子数组中每个都能满足下述条件 之一 ,则可以称其为数组的一种 有效 划分: 子数组 恰 由 2 个…...
Laravel Octane 和 Swoole 协程的使用分析
之前在工作中使用 Laravel Octane 的 concurrently 处理并发时,发现在队列和定时任务中不会触发并发效果。经过分析,作了如下猜测:队列和定时任务都属于一个独立的进程,与 Octane 服务无关,而 Octane concurrently 恰恰…...
腾讯云又双叕降价,云服务器配置优惠价格表2024新版报价
腾讯云服务器多少钱一年?62元一年起,2核2G3M配置,腾讯云2核4G5M轻量应用服务器218元一年、756元3年,4核16G12M服务器32元1个月、312元一年,8核32G22M服务器115元1个月、345元3个月,腾讯云服务器网txyfwq.co…...
【react native】css踩坑记录
1、IOS上面opacity重叠失效 在 iOS 上,当两个具有相同背景色的元素重叠时,不透明度(opacity)较低的元素会显示在较高的元素上方。 所以考虑使用rgba的形式。 // 对于下面这种写法,如果存在container和activeIndicat…...
ChatGPT学习第四周
📖 学习目标 ChatGPT实践操作 通过实际操作和练习,加深对ChatGPT功能的理解。 项目:创建一个ChatGPT应用案例 设计一个基于ChatGPT的小项目,将理论应用于实践。 ✍️ 学习活动 学习资料 《万字干货!ChatGPT 从零完…...
2D割草/吸血鬼游戏 性能优化——GPU Spine动画
视频中万人同屏方案(gpu动画、渲染、索敌、避障等功能),可某宝搜店铺:【游戏开发资源商店】获取整套方案源码。 在过去的几年里,割草、类吸血鬼玩法的游戏频出爆款,其丰富的技能、满屏特效、刷怪清屏的解压畅快是此类游戏的核心&…...
VSCode上搭建C/C++开发环境(vscode配置c/c++环境)Windows系统---保姆级教程
引言劝退 VSCode,全称为Visual Studio Code,是由微软开发的一款轻量级,跨平台的代码编辑器。大家能来搜用VSCode配置c/c,想必也知道VSCode的强大,可以手握一个VSCode同时编写如C,C,C#ÿ…...
[渗透教程]-013-嗅探工具-wireshark操作
文章目录 tor下载wireshark抓包类型启动场景实战tor下载 tor下载链接 zlibary暗网地址 2681506@gmail.com YanErrol123@wireshark Wireshark是网络封包分析软件,可以抓包.可以 使用winpcap与网卡直接进行数据交换.作用: 网络管理员使用wireshark来检测网络问题,网络工程师使用…...
NLP Seq2Seq模型
🍨 本文为[🔗365天深度学习训练营学习记录博客🍦 参考文章:365天深度学习训练营🍖 原作者:[K同学啊 | 接辅导、项目定制]\n🚀 文章来源:[K同学的学习圈子](https://www.yuque.com/mi…...
如何在 Linux 上使用 dmesg 命令
文章目录 1. Overview2.ring buffer怎样工作?3.dmesg命令4.移除sudo需求5. 强制彩色输出6.使用人性化的时间戳7.使用dmesg的人性化可读时间戳8.观察实时event9.检索最后10条消息10.搜索特定术语11.使用Log Levels12.使用Facility Categories13.Combining Facility a…...
WPF的DataGrid设置标题头
要设置DataGrid标题头的分割线、背景色和前景色等属性,您可以使用DataGrid的样式和模板来自定义标题头的外观。下面是详细解释以及示例代码: 分割线设置: 您可以使用DataGrid.ColumnHeaderStyle样式中的BorderThickness和BorderBrush属性来设…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...
RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...
Linux中《基础IO》详细介绍
目录 理解"文件"狭义理解广义理解文件操作的归类认知系统角度文件类别 回顾C文件接口打开文件写文件读文件稍作修改,实现简单cat命令 输出信息到显示器,你有哪些方法stdin & stdout & stderr打开文件的方式 系统⽂件I/O⼀种传递标志位…...
[特殊字符] 手撸 Redis 互斥锁那些坑
📖 手撸 Redis 互斥锁那些坑 最近搞业务遇到高并发下同一个 key 的互斥操作,想实现分布式环境下的互斥锁。于是私下顺手手撸了个基于 Redis 的简单互斥锁,也顺便跟 Redisson 的 RLock 机制对比了下,记录一波,别踩我踩过…...
表单设计器拖拽对象时添加属性
背景:因为项目需要。自写设计器。遇到的坑在此记录 使用的拖拽组件时vuedraggable。下面放上局部示例截图。 坑1。draggable标签在拖拽时可以获取到被拖拽的对象属性定义 要使用 :clone, 而不是clone。我想应该是因为draggable标签比较特。另外在使用**:clone时要将…...
二维数组 行列混淆区分 js
二维数组定义 行 row:是“横着的一整行” 列 column:是“竖着的一整列” 在 JavaScript 里访问二维数组 grid[i][j] 表示 第i行第j列的元素 let grid [[1, 2, 3], // 第0行[4, 5, 6], // 第1行[7, 8, 9] // 第2行 ];// grid[i][j] 表示 第i行第j列的…...
