记录--Vue3自定义一个Hooks,实现一键换肤
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助
核心
- 使用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)
并在<span>
;中显示MediaQueryList
的matches
属性值。如果视口的宽度小于或等于 600 像素,则输出将为 true,而如果窗口的宽度大于此宽度,则将输出 false。
<span class="mq-value"></span>
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<string>(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<string>(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里面的函数, 达到一键换肤效果
<div class="item">
<div class="left">
<div class="title">外观</div>
</div>
<div class="right">
<select v-model="appearance">
<option value="auto">{{ "自动" }}</option>
<option value="light"> {{ "浅色" }}</option>
<option value="dark"> {{ "深色" }}</option>
</select>
</div>
</div>
本文转载于:
https://juejin.cn/post/7237020208648634429
如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。
记录--Vue3自定义一个Hooks,实现一键换肤的更多相关文章
- 一种简单的实现:Android一键换肤功能
现在的APP开发,通常会提供APP的换肤功能,网上流传的换肤代码和实现手段过于复杂,我把原作者的代码重新整理抽取出来,转换成Eclipse项目,重新整理成正确.可直接运行的项目. 代码运行结果如图. ...
- Android一键换肤功能:一种简单的实现
Android一键换肤功能:一种简单的实现 现在的APP开发,通常会提供APP的换肤功能,网上流传的换肤代码和实现手段过于复杂,这里有一个开源实现,我找了一大堆,发现这个项目相对较为简洁:htt ...
- Android插件化的思考——仿QQ一键换肤,思考比实现更重要!
Android插件化的思考--仿QQ一键换肤,思考比实现更重要! 今天群友希望写一个关于插件的Blog,思来想去,插件也不是很懂,只是用大致的思路看看能不能模拟一个,思路还是比较重要的,如果你有兴趣的 ...
- 网上找到的一个jquery版网页换肤特效
这个跟我之前在锋利的JQuery那本书里看到的那个一模一样. <!DOCTYPE html> <html> <head> <meta name="& ...
- WPF 实现换肤功能
将所有控件的基本样式汇集到一个资源字典中,构成界面的基本样式文件,然后进行不同颜色皮肤的定制. 即在新的皮肤资源字典文件中引入基本样式文件,然后使用资源继承,并且只设置控件的颜色属性等,形成一个皮肤文 ...
- Scss换肤
项目中虽然没有一键换肤的要求,但是产品要求后期能换主题.在开发组件中涉及到主题的地方,要提取一些公用的变量,不要直接写死样式值.但是如果只是定义一些变量的话,只是完成控制颜色等值的提取.后期切换的话需 ...
- Android QMUI实战:实现APP换肤功能,并自动适配手机深色模式
Android换肤功能已不是什么新鲜事了,市面上有很多第三方的换肤库和实现方案. 之所以选择腾讯的QMUI库来演示APP的换肤功能,主要原因: 1.换肤功能的实现过程较简单.容易理解: 2.能轻松适配 ...
- 一文读懂HarmonyOS服务卡片怎么换肤
作者:zhenyu,华为软件开发工程师 关注HarmonyOS的小伙伴肯定对服务卡片已经很熟悉了.服务卡片(也简称为"卡片")是FA(FeatureAbility,元服务)的一种界 ...
- Android中插件开发篇之----应用换肤原理解析
一.前言 今天又到周末了,感觉时间过的很快呀.又要写blog了.那么今天就来看看应用的换肤原理解析.在之前的一篇博客中我说道了Android中的插件开发篇的基础:类加载器的相关知识.没看过的同学可以转 ...
- 自定义一个JdbcTemplate(增删改数据库中表记录)
需求: 自定义一个JdbcTemplate模板,实现增删改数据库中表记录的功能 1 package demo03; 2 3 import utils.JDBC_DBCP_Utils; 4 5 impo ...
随机推荐
- 【译】.NET 8 网络改进(三)
原文 | Máňa,Natalia Kondratyeva 翻译 | 郑子铭 简化的 SocketsHttpHandler 配置 .NET 8 添加了更方便.更流畅的方式来使用 SocketsHttp ...
- Windows 10 快捷键大全|日常办公效率加倍
## 复制.粘贴及其他常规 Ctrl + X 剪切选定项. Ctrl + C(或 Ctrl + Insert) 复制选定项. Ctrl + V(或 Shift + Insert) 粘贴选定项. ...
- 好书推荐之JAVA并发编程扛鼎之作:《Java并发编程实战》、《Java并发编程的艺术》
(pdf文档下载见文末) 大佬推荐 <Java 并发编程实战>,是一本完美的 Java 并发参考手册. 书中从并发性和线程安全性的基本概念出发,介绍了如何使用类库提供的基本并发构建块,用于 ...
- Centos7部署django+uwsgi+nginx 转载: https://www.cnblogs.com/wztshine/p/16172154.html
Centos7部署django+uwsgi+nginx Django + uwsgi + nginx on Centos7 wsgi 介绍 本小节来自 廖雪峰 wsgi 一文 一个Web应用的本质 ...
- JOISC 2018 记录
Day1 T1 Construction of Highway 每一次操作形如查询一条到根的链上的逆序对数,然后将这条链的权值全部修改成同一个权值. 发现这个操作类似于 LCT 的 Access 操作 ...
- MySQL案例-并行复制乱序提交引起的同步异常
现象描述 Slave在开启并行复制后, 默认会乱序提交事务, 可能会引起同步中断; Slave端表现为同步的SQL线程抛出异常, 为主键重复, 修改的数据行不存在等; GTID信息类似于: 9a2a5 ...
- 【Android 抓包对抗】客户端证书和域名校验绕过
1. 按照之前的方式(https://www.cnblogs.com/gradyblog/p/17197707.html)进行抓包发现证书校验失败 SSL handshake with client ...
- 【Android逆向】破解看雪9月算法破解第三题
这题的目标是算法还原,并写出注册机 1. 9月份算法第一题.apk 安装到手机 2. 随意输入账号密码,提示错误 3. apk拖入到jadx中 public native boolean regist ...
- java怎么打印一个对象的内存地址
在Java一般使用HashCode来代表对象的地址,但是两个相同的对象就不行了,两个相同的对象的hashcode是相同的. 如果要对比两个相同的对象的地址可以使用,System.identityHas ...
- 【C++ OOP 02 对象的初始化和清理】构造/析构函数、深/浅拷贝、初始化列表以及静态成员
[对象的初始化和清理] 生活中我们买的电子产品都基本会有出厂设置,在某一天我们不用时候也会删除一些自己信息数据保证安全 C++中的面向对象来源于生活,每个对象也都会有初始设置以及 对象销毁前的清理数据 ...