Vue3自定义Hooks一键换肤教程

news2024/9/29 11:32:33

核心

  • 使用CSS变量, 准备两套CSS颜色, 一套是在 light模式下的颜色,一套是在dark模式下的颜色
  • dark模式下的 CSS 权重要比 light 模式下的权重高, 不然当我们给html添加自定义属性[data-theme='dark']的时候, dark模式权重比light低,会一直不起效果
  • 当我们点击 dark 模式的时候, 给 html 设置自定义属性[data-theme='dark']
  • 当我们点击 light 模式的时候, 给 html 设置自定义属性[data-theme='light']
  • 在 dark 模式下, 会匹配到html[data-theme='dark']选择器下的样式
  • 在 light 模式下,由于我们没有设置html[data-theme='light']的方案, 那么他就匹配:root(即html)下的样式

两套样式代码大概如下(列了一部分):

:root {
  --color-body-bg: #ffffff;
  --color-text: #000;
  --color-secondary-bg-for-transparent: rgba(209, 209, 214, 0.28);
}

html[data-theme='dark'] {
  --color-body-bg: #222222;
  --color-text: #ffffff;
  --color-primary-bg-for-transparent: rgba(255, 255, 255, 0.12);
}

然后我们点击的时候,通过

 let theme = 'light'            // light / dark  
 document.documentElement.setAttribute('data-theme', theme)

这样就能实现简单的更换肤色功能了

什么? 你以为这就完了?好戏刚开始

跟随系统颜色

首先利用Window 的 'matchMedia()' 方法返回一个新的 MediaQueryList 对象,表示指定的媒体查询 (en-US)字符串解析后的结果。

如运行媒体查询(max-width: 600px)并在;中显示MediaQueryListmatches属性值。如果视口的宽度小于或等于 600 像素,则输出将为 true,而如果窗口的宽度大于此宽度,则将输出 false。

523ce202402261100158558.png

let mql = window.matchMedia('(max-width: 600px)');
document.querySelector(".mq-value").innerText = mql.matches; //此时小于或等于600像素时span 里面的结果为false

利用prefers-color-scheme [CSS媒体特性] 用于检测用户是否有将系统的主题色设置为亮色或者暗色。

.day   { background: #eee; color: black; }
.night { background: #333; color: white; }

@media (prefers-color-scheme: dark) {
  .day.dark-scheme   { background:  #333; color: white; }
  .night.dark-scheme { background: black; color:  #ddd; }
}

@media (prefers-color-scheme: light) {
  .day.light-scheme   { background: white; color:  #555; }
  .night.light-scheme { background:  #eee; color: black; }
}

两者相结合

matchMedia()prefers-color-scheme 结合在一起, 我们就可以通过 js 去给系统颜色为dark或 light 的情况下更换对应的 html自定义属性, 即[data-theme='dark']
[data-theme='light']

首先,我们先去获取主题颜色, 我们还没设置的时候,就默认是系统颜色, 设置了就把他存储起来,下次直接获取这个颜色

// 获取主题变量
let appearance = ref(localStorage.getItem('appearance') || 'auto')

// 查询当前系统主题颜色
const match = window.matchMedia("(prefers-color-scheme: dark)")

// 如果主题变量为 auto, 则跟随系统主题
if (appearance.value === 'auto') {
    followSystem()
} else {
    document.documentElement.setAttribute('data-theme', appearance.value)
}

function followSystem() {
    // 当前系统颜色是亮色还是暗色 , 设置对应的html[data-theme= 'dark' 或者'light']
    const theme = match.matches ? 'dark' : 'light'
    document.documentElement.setAttribute('data-theme', theme)
}

// 监听系统主题变化,电脑主题发生改变的时候就调用followSystem函数
match.addEventListener('change', followSystem)

封装成一个hooks

暴露出一个 useThemeColor函数, 返回一个对象, 对象里面返回我们的主题变量

/ 获取主题变量
let appearance = ref(localStorage.getItem('appearance') || 'auto')
// 查询当前系统主题颜色
const match:MediaQueryList = window.matchMedia("(prefers-color-scheme: dark)")
// 监听系统主题变化
match.addEventListener('change', followSystem)

function followSystem() {
    const theme = match.matches ? 'dark' : 'light'
    document.documentElement.setAttribute('data-theme', theme)
}

watchEffect(() => {
// 如果主题变量为 auto, 则跟随系统主题
    if (appearance.value === 'auto') {
        followSystem()
    } else {
        document.documentElement.setAttribute('data-theme', appearance.value)
    }
})


export default function useThemeColor() {
    return {
        appearance,
    }
}

使用hooks

导入我们export出来的函数

import useThemeColor from '../hooks/useThemeColor'

使用函数,注意, 这里返回的 apprance 已经是一个响应式数据

const { appearance } = useThemeColor()

使用 v-model 绑定apprance,直接使用apprance , 当我们切换颜色的时候, 就会调用watchEffect里面的函数, 达到一键换肤效果

bdfa8202402261100442073.png

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

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

相关文章

消息队列 MQ

文章目录 1. MQ 相关概念1.1 什么是 MQ1.2 为什么要用 MQ1.3 MQ 分类1.4 MQ 的选择 1. MQ 相关概念 1.1 什么是 MQ MQ(message queue),从字面意思上看,本质是个队列,FIFO 先入先出,只不过队列中存放的内容是 message 而已&#x…

Linux--文件类型与权限

Linux上一切皆文件; 蓝色的是目录文件 Linux不以文件的扩展名来区分文件类型,而是在文件属性中有一列专门记录文件类型. ls -l 可以查看 普通文件:.c .cpp .h .txt .pdf .xls (-) 目录文件:文件夹 (d) 管道文件:用于进程间通信的一种文件 (p) 链接文件:相当于W…

[ROS 系列学习教程] rosbag C++ API

ROS 系列学习教程(总目录) 本文目录 一、rosbag::Bag1.1 常用接口1.2 其他接口 二、rosbag::View2.1 常用接口2.1.1 代码示例 rosbag 的 C API 主要有两个类,用于写bag文件的Bag类,和用于读bag文件的View类。 一、rosbag::Bag 用于写bag文件。 头文件…

【C语言步行梯】分支语句if...else、switch详谈

🎯每日努力一点点,技术进步看得见 🏠专栏介绍:【C语言步行梯】专栏用于介绍C语言相关内容,每篇文章将通过图片代码片段网络相关题目的方式编写,欢迎订阅~~ 文章目录 什么是语句?引入分支语句&am…

力扣hot10---大根堆+双端队列

题目&#xff1a; 大根堆思路&#xff1a; 维护最大值&#xff0c;应该首先想到大根堆。C中对应着priority_queue&#xff0c;这里用pair<int,int>来记录对应的值和在nums中的索引。所以有priority_queue<pair<int,int>> q。在大根堆中&#xff0c;用q.top()…

C++的类与对象(三):构造函数、析构函数、对象的销毁顺序

目录 类的6个默认成员函数 构造函数 语法 特性 析构函数 特性 对象的销毁顺序​​​​​​​​​​​​​​ 类的6个默认成员函数 问题&#xff1a;一个什么成员都没的类叫做空类&#xff0c;空类中真的什么都没有吗&#xff1f; 基本概念&#xff1a;任何类在什么都不…

使用swagger生成接口文档

使用swagger生成接口文档 有时候一份清晰明了的接口文档能够极大地提高前后端双方的沟通效率和开发效率。本文将介绍如何使用swagger生成接口文档。 swagger生成接口文档 swagger介绍 Swagger本质上是一种用于描述使用JSON表示的RESTful API的接口描述语言。Swagger与一组开…

MT笔试题

前言 某团硬件工程师的笔试题&#xff0c;个人感觉题目的价值还是很高的&#xff0c;分为选择题和编程题&#xff0c;选择题考的是嵌入式基础知识&#xff0c;编程题是两道算法题&#xff0c;一道为简单难度&#xff0c;一道为中等难度 目录 前言选择题编程题 选择题 C语言中变…

突破编程_前端_JS编程实例(目录导航)

1 开发目标 目录导航组件旨在提供一个滚动目录导航功能&#xff0c;使得用户可以方便地通过点击目录条目快速定位到对应的内容标题位置&#xff0c;同时也能够随着滚动条的移动动态显示当前位置在目录中的位置&#xff1a; 2 详细需求 2.1 标题提取与目录生成 组件需要能够自…

【PHP+代码审计】PHP基础——运算符

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【Java、PHP】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收…

数据分析-Pandas两种分组箱线图比较

数据分析-Pandas两种分组箱线图比较 数据分析和处理中&#xff0c;难免会遇到各种数据&#xff0c;那么数据呈现怎样的规律呢&#xff1f;不管金融数据&#xff0c;风控数据&#xff0c;营销数据等等&#xff0c;莫不如此。如何通过图示展示数据的规律&#xff1f; 数据表&am…

【prompt四】Domain Prompt Learning for Efficiently Adapting CLIP to Unseen Domains

motivation 领域泛化(DG)是一个复杂的迁移学习问题,旨在学习未知领域的可泛化模型。最近的基础模型(FMs)对许多分布变化都具有鲁棒性,因此,应该从本质上提高DG的性能。在这项工作中,我们研究了采用视觉语言基础模型CLIP来解决图像分类中的DG问题的通用方法。虽然ERM使用标…

【设计模式】(四)设计模式之工厂模式

1. 工厂模式介绍 工厂模式&#xff08;Factory Pattern&#xff09;是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式&#xff0c;它提供了一种创建对象的最佳方式。 工厂模式有三种实现方式&#xff1a; 简单工厂模式工厂方法模式抽象工厂模式 2. 工厂方…

部署LVS+Keepalived高可用群集(抢占模式,非抢占模式,延迟模式)

目录 一、LVSKeepalived高可用群集 1、实验环境 2、 主和备keepalived的配置 2.1 yum安装ipvsadm和keepalived工具 2.2 添加ip_vs模块并开启ipvsadm 2.3 修改keepalived的配置文件 2.4 调整proc响应参数&#xff0c;关闭linux内核的重定向参数响应 2.5 将主服务器的kee…

SSRF服务器请求伪造原理和pikachu靶场实验

★★免责声明★★ 文章中涉及的程序(方法)可能带有攻击性&#xff0c;仅供安全研究与学习之用&#xff0c;读者将信息做其他用途&#xff0c;由Ta承担全部法律及连带责任&#xff0c;文章作者不承担任何法律及连带责任。 1、SSRF简介 SSRF全称&#xff1a;Server-Side Request…

深入理解操作系统Operator System(2)

目录 操作系统对上的管理 系统调用接口 用户操作接口&#xff08;库函数&#xff09; 系统调用和库函数的概念 结构层次示意图 总结 为什么要有操作系统❓ 上次主要介绍了操作系统的"管理"和操作系统对下的管理。本篇主要是对上的管理。 操作系统对上的管理 …

【运维】本地部署Gemma模型(图文)

工具简介 我们需要使用到两个工具&#xff0c;一个是Ollama&#xff0c;另一个是open-webui。 Ollama Ollama 是一个开源的大语言平台&#xff0c;基于 Transformers 和 PyTorch 架构&#xff0c;基于问答交互方式&#xff0c;提供大语言模型常用的功能&#xff0c;如代码生…

软考高级:电子商务角色和类型概念和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

个人网站展示(静态)

大学期间做了一个个人博客网站&#xff0c;纯H5编码的网站&#xff0c;利用php搭建了一个留言模块。 有需要源码的同学&#xff0c;可以联系我~ 首页&#xff1a; IT杂记模块 文人墨客模块 劳有所获模块 生活日志模块 关于我 一个推崇全栈开发的前端开发人员 微信: itrzzh …

人工智能时代的产品管理:如何成为下一代引领者

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…