记录--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 ...
随机推荐
- AT_arc125_c [ARC125C] LIS to Original Sequence 题解
题目传送门 前置知识 贪心 | 构造 解法 对于任意一个未加入序列 \(P\) 的数 \(x<A_{i}(1 \le i \le k-1)\),如果其放在了 \(A_{i}\) 的前面,会导致最 ...
- BZOJ3156 防御准备 题解
原题 令 \(S_{i} =\sum\limits_{j=1}^{i}j\) , \(f_{i}\) 为处理到第 \(i\) 个位置放置守卫塔的最小花费. 观察题意,容易得到在\((1 \le j \ ...
- NC17193 简单瞎搞题
题目链接 题目 题目描述 一共有 n个数,第 i 个数是 xi xi 可以取 [li , ri] 中任意的一个值. 设 \(S = \sum{{x_i}^2}\) ,求 S 种类数. 输入描述 第一行 ...
- BUG管理系统(Mantis)迁移实战
Mantis迁移实战 名词解释 Mantis: 开源的BUG管理平台Mantis,也做MantisBT. 同档次产品有EasyBUG,QC,BugFree,Bugzila. Xa ...
- spring boot使用自带缓存
项目地址:https://gitee.com/indexman/spring_boot_in_action 下面就介绍一下如何使用spring boot自带的缓存.按步骤来操作即可,不懂的可以去看项目 ...
- dp题单——区间dp
一.基本概念 1.链式区间dp for(int len = 2; len <= n; len++){ //枚举区间长度 for(int i = 1; i + len - 1 <= n; i ...
- [WEB安全] CSRF攻击和防御
一.什么是CSRF 跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或 ...
- 【LeetCode二叉树#10】从中序与后序(或者前序)遍历序列构造二叉树(首次构造二叉树)
从中序与后序遍历序列构造二叉树 力扣题目链接(opens new window) 根据一棵树的中序遍历与后序遍历构造二叉树. 注意: 你可以假设树中没有重复的元素. 例如,给出 中序遍历 inorde ...
- redis-cluster 性能调优
关闭RDB防止fork进程的内存溢出问题 save "" appendonly=yes 防止某个节点挂掉,整个cluster挂掉的问题 cluster-require-full-c ...
- 图数据库 Nebula Graph 的代码变更测试覆盖率实践
对于一个持续开发的大型工程而言,足够的测试是保证软件行为符合预期的有效手段,而不是仅仅依靠 code review 或者开发者自己的技术素质.测试的编写理想情况下应该完全定义软件的行为,但是通常情况都 ...
