主题替换解决方案-打造完善多主题

目录

01: 主题替换原理分析

02: TailWind DarkMode 原理

03: 为组件增加 Dark 适配

04: DarkMode 在复杂应用中的实现逻辑分析

05: DarkMode 在复杂应用中的实现

06: 跟随系统的主题变更

07: 总结


01: 主题替换原理分析

        主题替换原理:通过类名来控制对应的样式(主题),当类名发生变化时,即完成了主题替换。

02: TailWind DarkMode 原理

// tailwind.config.jsmodule.exports = {// 手动切换暗黑模式darkMode: 'class'……
}
// 受影响的元素
<div class="bg-white dark:bg-zinc-800"></div>// 设置主题
<html class="dark"></html>

03: 为组件增加 Dark 适配

        各个组件添加 " class='dark:bg-zinc-800 dark:hover:bg-zinc-300' " 。

04: DarkMode 在复杂应用中的实现逻辑分析

        1. 监听主题的切换行为。

        2. 根据行为,保存当前需要展示的主题到 vuex 中。

        3. 根据 vuex 中保存的当前主题,展示 header-theme 下的显示图标。

        4. 根据 vuex 中保存的当前主题,修改 html 的 class。

05: DarkMode 在复杂应用中的实现

- store
- - modules
- - - theme.js
- - getters.js
- - index.js
// src/store/modules/theme.jsimport { THEME_LIGHT } from '@/constants'export default {namespaced: true,state: () => ({// 当前主题模式themeType: THEME_LIGHT}),mutations: {changeThemeType(state, newTheme) {state.themeType = newTheme}}
}
// src/store/index.jsimport theme from './modules/theme'const store = createStore({……modules: {theme,}……
}
// src/store/getters.jsexport default {themeType: (state) => state.theme.themeType
}
// src/views/layout/components/header/header-theme.vue<script setup>import { useStore } from 'vuex'// 构建渲染数据源const themeArr = [{id: '0',type: THEME_LIGHT,icon: 'theme-light',name: '极简白'},{id: '1',type: THEME_DARK,icon: 'theme-dark',name: '极夜黑'},{id: '2',type: THEME_SYSTEM,icon: 'theme-system',name: '跟随系统'}]const store = useStore()/*** menu 切换事件*/const onItemClick = (themeItem) => {store.commit('theme/changeThemeType', themeItem.type)}/*** 控制图标展示*/const svgIconName = computed(() => {const findTheme = themeArr.find((theme) => {return theme.type === store.getters.themeType}return findTheme?.icon || themeArr[0].type})
</script>
- utils
- - theme.js
// src/utils/theme.jsimport { watch } from 'vue'
import store from '../store'/*** 初始化主题*/
export default () => {// 1. 当主题发生改变时,或者当进入系统时,可以进行 html class 的配置watch(() => store.getters.themeType,(val) => {// html 的 classlet themeClassName = ''switch (val) {case THEME_LIGHT:themeClassName = 'light'breakcase THEME_DARK:themeClassName = 'dark'break// 修改 html 的 classdocument.querySelector('html').className = themeClassName},{// 初始执行一次immediate: true})
}
// src/main.jsimport useTheme from './utils/theme'useTheme()

06: 跟随系统的主题变更

想要生成跟随系统的主题变更,那么我们就需要 **监听系统的主题变化**

想要做到这一点,可以利用 Window.matchMedia() 方法,该方法接受一个 mediaQueryString (媒体查询解析的字符串),该字符串我们可以传递 prefers-color-schema,即 window.matchMedia('(prefers-color-schema: dark)') 方法。

该方法可以返回一个 MediaQueryList 对象:

1. 该对象存在一个 change 事件,可以监听 主题发生变更 的行为。

2. 同时存在一个 matches 属性,该属性为 boolean 性的值:

        1. true:深色主题

        2. false:浅色主题

那么据此,可生成以下代码,在 src/utils/theme.js 中:

import store from '@/store'
import { watch } from 'vue'
import { THEME_LIGHT, THEME_DARK, THEME_SYSTEM } from '@/constants'/*** 监听系统主题变更*/
let matchMedia
const watchSystemThemeChange = () => {// 仅需初始化一次即可if (matchMedia) returnmatchMedia = window.matchMedia('(prefers-color-scheme: dark)')// 监听主题变更matchMedia.onchange = function () {changeTheme(THEME_SYSTEM)}
}/*** 变更主题* @param {*} theme 主题的标记常量*/
const changeTheme = (theme) => {// html 的 classlet themeClassName = ''switch (theme) {case THEME_LIGHT:themeClassName = 'light'breakcase THEME_DARK:themeClassName = 'dark'breakcase THEME_SYSTEM:watchSystemThemeChange()themeClassName = matchMedia.matches ? 'dark' : 'light'break}// 修改 html 的 classdocument.querySelector('html').className = themeClassName
}/*** 初始化主题*/
export default () => {watch(() => store.getters.themeType, changeTheme, {// 初始执行一次immediate: true})
}

07: 总结

主要讲解了 主题替换的功能,包含以下 4 个主要方面:

1. 主题替换原理

2. tailwind 主题替换原理

3. 复杂应用中的实现方案

4. 跟随系统的主体变更

目前市面上很多的 组件库 也都包含了主题替换的功能,它们的实现原理其实也就是本文章中所讲解的方式。

看完本文章之后,应该也可以对主题替换这样的普适功能有更加深入的了解啦~ 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/11557.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2023-2024 联邦推荐 × 顶会

目录 AAAI2024 Federated Contextual Cascading Bandits with Asynchronous Communication and Heterogeneous Users General Commerce Intelligence: Glocally Federated NLP-Based Engine for Privacy-Preserving and Sustainable Personalized Services of Multi-Merchan…

Kubernetes——命令指南

目录 前言 1.检查集群状态 2.使用Pod 3.使用部署 4.使用服务 5.使用 ConMap 和 Secret 6.调试与故障排除 7.清理 8.使用命名空间 9.管理持久卷 10.处理节点 11.资源配额和限制范围 12.访问API对象 13.总结 前言 kubectl 是针对Kubernetes集群运行命令的命令行界…

怎么通过微信小程序实现远程控制8路控制器/断路器

怎么通过微信小程序实现远程控制8路控制器/断路器呢&#xff1f; 本文描述了使用微信小程序调用HTTP接口&#xff0c;实现控制8路控制器/断路器&#xff0c;支持8路输出&#xff0c;均可独立控制&#xff0c;可接入各种电器。 可选用产品&#xff1a;可根据实际场景需求&#…

DS:顺序表、单链表的相关OJ题训练(2)

欢迎各位来到 Harper.Lee 的学习世界&#xff01; 博主主页传送门&#xff1a;Harper.Lee的博客主页 想要一起进步的uu欢迎来后台找我哦&#xff01; 一、力扣--141. 环形链表 题目描述&#xff1a;给你一个链表的头节点 head &#xff0c;判断链表中是否有环。如果链表中有某个…

提升网络性能,解决网络故障,了解AnaTraf网络流量分析仪

在当今数字化时代&#xff0c;网络性能监测与诊断(Network Performance Monitoring and Diagnosis,NPMD)成为了企业和个人关注的焦点。随着网络流量不断增长&#xff0c;确保网络的稳定性和高效性变得更加重要。在这个领域&#xff0c;AnaTraf网络流量分析仪是您不可或缺的得力…

从“金事通”带给我意想不到的来说--“数据是架构的中心”

背景 上周一个保险的销售人员来找我完成一定的售后流程。其中有一项是请我下载一个叫 金事通的 APP。说实在的我根本没听过。她说这是政治任务。我想不是有你们保险公司的APP了嘛。为什么还要我安装。没办法先安装吧。 经历了注册、人脸识别的步骤后。可以登录了。注册短信发…

使用Docker+Jar方式部署微服务工程(前后端分离)看着一篇就够了

本篇教程的使用到的技术有springboot、springcloud、Nacos、Docker、Nginx部署前后端分离访问的微服务。 部署一下Nacos 首先我们需要在服务器中&#xff08;或者本地部署启动一下Nacos&#xff09;&#xff0c;这里我采用服务器的方式进行部署&#xff0c;这里有一点不一样的…

前端开发者必备:Nginx入门实战宝典,从部署到优化一网打尽

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 引言 &#x1f44b;一、Nginx简介 &#x1f4da;二、常见的Web服务器架构 &#x1f300;&#x1f4cc; 架构概述&#x1f4cc; Nginx的深入探讨 三、正向代理与反向代理 &#x1f52e;&#x1f4cc; 正向代理工作原理&#…

Leecode热题100---1:两数之和

题目&#xff1a;从nums中找出两个元素&#xff0c;它们的和等于target&#xff0c;返回下标。 C&#xff1a; 1、直接暴力法 写嵌套循环&#xff0c;让每一个元素和其他元素分别相加&#xff0c;判断和是否等于target&#xff0c;等于就返回下标。 #include <iostream>…

RabbitMQ(四种使用模式)

文章目录 1.Fanout&#xff08;广播模式&#xff09;1.基本介绍2.需求分析3.具体实现1.编写配置类 RabbitMQConfig.java2.编写生产者&#xff0c;发送消息到交换机 MQSender.java3.编写消费者&#xff0c;接受消息 MQReceiver.java4.控制层调用方法&#xff0c;发送信息到交换机…

git error index file corrupt

错误提示&#xff1a; error: bad signature 0x00000000 fatal: index file corrupt 场景复现&#xff1a;在使用git add .提交代码到缓冲区时电脑宕机&#xff0c;重启后再次提交代码会出现该提示 原因分析&#xff1a;.git目录下的index文件损坏 解决方式&#xff1a; 删…

工程师工具箱系列(3)Arthas

文章目录 工程师工具箱系列&#xff08;3&#xff09;Arthas安装与准备Arthas插件使用场景查看某个变量值ognl方式调用Bean方法tt(TimeTunel)方式调用Bean的方法ognl调用带参数方法 资源总览 工程师工具箱系列&#xff08;3&#xff09;Arthas Java诊断利器 安装与准备 window…

LabVIEW学习记录3 - 自定义函数

LabVIEW学习记录3 - 自定义函数 一、LabVIEW学习记录二、自定义函数及函数调用 一、LabVIEW学习记录 【labVIEW】学习记录LabVIEW学习记录2 - MySQL数据库连接与操作LabVIEW学习记录 - 实时显示时间LabVIEW学习记录4-局部变量、全局变量、共享变量 二、自定义函数及函数调用 …

C++入门-stack和queue(下)

大家好啊&#xff0c;在这先祝天下的母亲节日快乐啦&#xff01;现在呢&#xff0c;给大家带来C中priority_queue和容器适配器的相关知识点 3.1 C 中的优先队列&#xff08;priority_queue&#xff09;介绍 优先队列&#xff08;priority_queue&#xff09;是一种特殊的队列…

洛谷 P6218 [USACO06NOV] Round Numbers S 题解 数位dp

[USACO06NOV] Round Numbers S 题目描述 如果一个正整数的二进制表示中&#xff0c; 0 0 0 的数目不小于 1 1 1 的数目&#xff0c;那么它就被称为「圆数」。 例如&#xff0c; 9 9 9 的二进制表示为 1001 1001 1001&#xff0c;其中有 2 2 2 个 0 0 0 与 2 2 2 个 1 …

Linux部署Heartbeat

环境信息&#xff1a; 10.1.13.75 master 10.1.13.140 slave 10.1.13.247 VIP 一&#xff0c;基础环境处理 1&#xff0c;修改主机名 master节点 hostnamectl set-hostname master slave节点 hostnamectl set-hostname slave 2&#xff0c;修改/etc/hosts vi /etc/hos…

transformer与beter

transformer与beter 解码和编码器含义tokizer标记器和one-hot独热编码编码解码--语义较好的维度空间矩阵相乘--空间变换编码理解如何构造降维的嵌入矩阵--实现到达潜空间上面是基础&#xff0c;下面是transformer正文自注意力机制注意力分数--上下文修正系数为什么需要KQ两个矩…

设计模式-07 设计模式-观察者模式(Observer Pattern)

设计模式-07 设计模式-观察者模式&#xff08;Observer Pattern&#xff09; 1.定义 观察者模式是一种软件设计模式&#xff0c;它定义了一种一对多的依赖关系&#xff0c;其中一个对象&#xff08;称为“主题”&#xff09;维护了一个依赖对象的列表&#xff08;称为“观察者”…

ssm125四六级报名与成绩查询系统+jsp

四六级报名与成绩查询系统的设计与实现 摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对四六级报名信息管理混乱&am…

达梦数据插入操作的深坑

提示错误&#xff1a;Only if specified in the column list and SET IDENTITY_INSERT is ON, then identity column could be assigned value 插入的语句采用缺省的方式实现&#xff0c;执行插入操作失败&#xff1b; 原因分析&#xff1a; 1.自增长的SQL表里面插入指定ID的…