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

目录

01: 主题替换原理分析

02: TailWind DarkMode 原理

03: 为组件增加 Dark 适配

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

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

06: 跟随系统的主题变更

07: 总结


01: 主题替换原理分析

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

02: TailWind DarkMode 原理

// tailwind.config.js

module.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.js

import { THEME_LIGHT } from '@/constants'

export default {
    namespaced: true,
    state: () => ({
        // 当前主题模式
        themeType: THEME_LIGHT
    }),
    mutations: {
        changeThemeType(state, newTheme) {
            state.themeType = newTheme
        }
    }
}
// src/store/index.js

import theme from './modules/theme'

const store = createStore({
    ……
    modules: {
        theme,
    }
    ……
}
// src/store/getters.js

export 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.js

import { watch } from 'vue'
import store from '../store'

/**
 * 初始化主题
 */
export default () => {
    // 1. 当主题发生改变时,或者当进入系统时,可以进行 html class 的配置
    watch(
        () => store.getters.themeType,
        (val) => {
            // html 的 class
            let themeClassName = ''
            switch (val) {
                case THEME_LIGHT:
                    themeClassName = 'light'
                    break
                case THEME_DARK:
                    themeClassName = 'dark'
                    break
            // 修改 html 的 class
            document.querySelector('html').className = themeClassName
        },
        {
            // 初始执行一次
            immediate: true
        }
    )
}
// src/main.js

import 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) return
  matchMedia = window.matchMedia('(prefers-color-scheme: dark)')
  // 监听主题变更
  matchMedia.onchange = function () {
    changeTheme(THEME_SYSTEM)
  }
}

/**
 * 变更主题
 * @param {*} theme 主题的标记常量
 */
const changeTheme = (theme) => {
  // html 的 class
  let themeClassName = ''
  switch (theme) {
    case THEME_LIGHT:
      themeClassName = 'light'
      break
    case THEME_DARK:
      themeClassName = 'dark'
      break
    case THEME_SYSTEM:
      watchSystemThemeChange()
      themeClassName = matchMedia.matches ? 'dark' : 'light'
      break
  }
  // 修改 html 的 class
  document.querySelector('html').className = themeClassName
}

/**
 * 初始化主题
 */
export default () => {
  watch(() => store.getters.themeType, changeTheme, {
    // 初始执行一次
    immediate: true
  })
}

07: 总结

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

1. 主题替换原理

2. tailwind 主题替换原理

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

4. 跟随系统的主体变更

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

(done) 什么是马尔可夫链?Markov Chain

参考视频&#xff1a;https://www.bilibili.com/video/BV1ko4y1P7Zv/?spm_id_from333.337.search-card.all.click&vd_source7a1a0bc74158c6993c7355c5490fc600 如下图所示&#xff0c;马尔可夫链条实际上就是 “状态机”&#xff0c;只不过状态机里不同状态之间的边上是 “…

向银行家应用程序添加日期

● 首先我们将下面图片上的时间更换成现在的时间 const now new Date(); const day now.getDate(); const month now.getMonth() 1; const year now.getFullYear(); const hour now.getHours(); const min now.getMinutes();labelDate.textContent ${day}/${month}/$…

数据降维-主成分分析PCA

1.背景&#xff1a; 在以前计算能力还很弱的年代&#xff0c;我们要分析经济数据是一件很困难的事情&#xff0c;所以我们需要对指标特征进行降维&#xff1b; 2.数据降维的意义&#xff1a; 一般我们降维的特征数据彼此之间是存在一定的相关性的&#xff0c; 二维降至一维…

车载电子电器架构 —— Vector对于车载以太网的解决方案(协议栈)

车载电子电器架构 —— Vector对于车载以太网的解决方案(协议栈) 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你…

252 基于MATLAB的自适应差分阈值法检测心电信号的QRS波

基于MATLAB的自适应差分阈值法检测心电信号的QRS波&#xff0c;QRS波群反映左、右心室除极电位和时间的变化&#xff0c;第一个向下的波为Q波&#xff0c;向上的波为R波&#xff0c;接着向下的波是S波。通过GUI进行数据处理&#xff0c;展示心率和QRS。程序已调通&#xff0c;可…

COMSOL粗略估算计算时间

COMSOL粗略估算模型计算时间 针对反复修改调试的有限元模型&#xff0c;需要大致估算有限元模型的计算时间。经查阅&#xff0c;模型求解的自由度数和求解时间密切相关。 测试条件 测试模型为声-固耦合模型&#xff0c;电脑内存32G&#xff0c;CPU-i7-10700K&#xff0c;核显…

【GD32】03 - EXTI外部中断

EXTI EXTI&#xff0c;全称External Interrupt/Event Controller&#xff0c;即外部中断/事件控制器&#xff0c;是微控制器中的一个重要组成部分。它主要用于管理来自外部设备的中断和事件请求。以下是关于EXTI的详细介绍&#xff1a; 功能概述&#xff1a; EXTI管理了控制器的…

OpenAI 人工智能搜索产品即将推出,文本和图像都支持?!

OpenAI 人工智能搜索产品即将推出 OpenAI 计划于下周一(5 月 13 日)正式公布其人工智能搜索产品,不过报道中强调具体公告日期可能发生变化。OpenAI 拒绝对路透社的报道置评。外媒 The Information 在今年 2 月的报道中指出,OpenAI 一直在秘密开发其自家网络搜索服务,并将获…

C++初阶学习第七弹——探索STL奥秘(二)——string的模拟实现

标准库中的string&#xff1a;C初阶学习第六弹——string&#xff08;1&#xff09;——标准库中的string类-CSDN博客 前言&#xff1a; 在前面我们已经学习了如何使用标准库中的string类&#xff0c;但作为一个合格的程序员&#xff0c;我们不仅要会用&#xff0c;还要知道如…

Midjourney Imagine API 申请及使用

Midjourney Imagine API 申请及使用 申请流程 要使用 Midjourney Imagine API&#xff0c;首先可以到 Midjourney Imagine API 页面点击「Acquire」按钮&#xff0c;获取请求所需要的凭证&#xff1a; 如果你尚未登录或注册&#xff0c;会自动跳转到登录页面邀请您来注册和登…

[嵌入式系统-77]:RT-Thread-快速上手:嵌入式系统调测工具大全

目录 1. JTAG 下载调试器&#xff1a; 2. J-Link 仿真器&#xff1a; 3. ICE&#xff08;In-Circuit Emulator&#xff09;&#xff1a; 4. ROM监视器&#xff08;ROM Monitor&#xff09;&#xff1a; 5. 终端仿真工具&#xff1a; 6. 总线抓取工具&#xff1a; 7. 静态…

【教学类-55-02】20240512图层顺序挑战(四格长条纸加黑色边框、4*4、7张 、43200张去掉非7色有23040张,去掉重复样式有几种?)

作品展示 背景需求&#xff1a; 之前的代码吗存在几个问题&#xff0c;最大的问题是不能生成“”长条黑边框”” 【教学类-55-01】20240511图层顺序挑战&#xff08;四格长条纸&#xff09;&#xff08;4*4&#xff09;和“手工纸自制参考图”-CSDN博客文章浏览阅读485次&…

2024第八季完美童模 【星光】品牌赛区 【直通】赛 完美收官

2024年5月1日&#xff0c;春风徐徐的【星光品牌赛区】热闹非凡&#xff0c;备受瞩目的第八季完美童模【星光品牌赛区】赛区【直通赛】在这一天正式拉开了帷幕。比赛现场&#xff0c;童模们身着华服&#xff0c;在舞台上演绎了“亚特兰蒂斯”的时尚主题赛。 参赛选手们身着带有海…

【优先级队列】Leetcode 最后一块石头的重量

题目讲解 1046. 最后一块石头的重量 算法讲解 根据题目的意思&#xff0c;为了寻找到本次数组中的最大的两个值&#xff0c;我们需要使用一个数据结构&#xff1a;堆&#xff0c;使用大堆&#xff0c;每一次出两个数据&#xff0c;这两个数据就是当前数组中的两个最大值&…

拉链表实现过程+案例

第一种 1.从ODS层获取增量数据(上一天新增和更新的数据) 2.拿着DWD原始拉链表数据 left join 增量数据 ,修改原始拉链中历史数据的结束时间 3.拿着left join 的结果集 union all 增量数据 4.把最新的拉链数据优先保存到DWD对应的临时表中 5.使用insertselect 方式把临时表中…

力扣75. 颜色分类

Problem: 75. 颜色分类 文章目录 题目描述思路及解法复杂度Code 题目描述 思路及解法 由于题目只提供0&#xff0c;1&#xff0c;2分别代表颜色红、白、蓝&#xff0c;并按此排序&#xff0c;那么我们可以遍历两次数组&#xff0c;第一次将0&#xff0c;全部放到数组前面一部分…

Python如何绘制直流电机开闭环特性曲线?matplotlib

import matplotlib.pyplot as plt from pylab import mplmpl.rcParams[font.sans-serif] [FangSong] # 指定默认字体 mpl.rcParams[axes.unicode_minus] False # 解决保存图像是负号-显示为方块的问题# 数据集1 n1 [1206, 1174, 1141, 1116, 1037, 986] Id1 [0.505, 0.55…

GEVernova推出GEV新能源平台,引领新能源未来

近日&#xff0c;全球领先的能源设备制造和服务公司 GE Vernova 宣布推出 GEV 新能源平台&#xff0c;这是一个将金融、科技和产业深度融合的全新投资平台。GEV 新能源平台旨在为用户提供一站式可持续新能源投资解决方案&#xff0c;助力全球新能源转型和可持续发展。 新能源已…

车载电子电器架构 —— UDS Service 11介绍

车载电子电器架构 —— UDS Service 11介绍 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证…

Dev-C++的下载和安装教程(超详细图文,小白入门)

Dev-C&#xff08;或者叫做Dev-Cpp&#xff09;是Windows环境下的一个轻量级C/C集成开发环境&#xff08;IDE&#xff09;。它是一款自由软件&#xff0c;遵守GPL许可协议分发源代码。 Dev-C集合了功能强大的源码编辑器、MingW64/TDM-GCC编译器、GDB调试器和AStyle格式整理器等…