记录--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 ...
随机推荐
- CentOS7 开机网卡加载失败
服务器CentOS7一开,发现web服务无法访问.最终用ifconfig发现,网卡没有加载,连个IP地址都没有. 这时使用命令 service network restart 试图重启服务器网络.不料 ...
- Maven如何打包可执行jar包
假设我有一个maven项目叫:hello-world 新建一个HelloWorld类: package com.dylan.mvnbook.helloworld; public class Hello ...
- win终端利器-Cmder的安装使用
cmder 官网:https://cmder.app/ 安装 直接选择full版本下载,完成后解压即可 启动 直接双击Cmder.exe 如果每次都进入到 Cmder 解压目录双击 Cmder.exe ...
- 【Azure 事件中心】Spring Cloud Stream Event Hubs Binder 发送Event Hub消息遇见 Spec. Rule 1.3 - onSubscribe, onNext, onError and onComplete signaled to a Subscriber MUST be signaled serially 异常
问题描述 开发Java Spring Cloud应用,需要发送消息到Azure Event Hub中.使用 Spring Cloud Stream Event Hubs Binder 依赖,应用执行一 ...
- 【Azure Redis 缓存】Azure Redis服务开启了SSL(6380端口), PHP如何访问缓存呢?
问题描述 使用6379端口连接Azure Redis服务,连接失败.因为默认情况下Azure Redis的设置没有打开6379的端口.需要使用SSL(6380端口)进行连接,但是遇见了无法连接的问题. ...
- 【Azure Redis 缓存】C#程序是否有对应的方式来优化并缩短由于 Redis 维护造成的不可访问的时间
问题描述 C#程序是否有对应的方式来优化并缩短由于 Redis 维护造成的不可访问的时间? Redis维护说明: Redis 服务维护时,会把副本节点提升为主节点,且旧主节点关闭现有连接时,这个时候, ...
- spark 下java list 或者scala list 转DataFrame or DataSet 总结
一.JAVA list 转 DataFrame or DataSet case class CaseJava( var num: String, var id: String, var start_t ...
- C++11新特性的一些用法举例①
//字符串字面量/*常用:1.原始字符串字面量 --- 括号内保持原样输出 --- 没有转义字符,如\n不再是换行,而是直接输出字面量\nR"(str)"; 实例: R" ...
- RocketMQ(9) 消息堆积与消费延迟
消息堆积与消费延迟 1 概念 消息处理流程中,如果Consumer的消费速度跟不上Producer的发送速度,MQ中未处理的消息会越来越多(进的多出的少),这部分消息就被称为堆积消息.消息出现堆积进而 ...
- 18 Codeforces Round 853 (Div. 2)C. Serval and Toxel's Arrays(算贡献)
C. Serval and Toxel's Arrays 这种题目做多了应该很容易从贡献的角度去考虑了. 考虑当前版本对答案的贡献,首先这个版本和其他版本取交集至少会包含它本身所以直接先把\(i * ...
