这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

核心

  • 使用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>;中显示MediaQueryListmatches属性值。如果视口的宽度小于或等于 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,实现一键换肤的更多相关文章

  1. 一种简单的实现:Android一键换肤功能

    现在的APP开发,通常会提供APP的换肤功能,网上流传的换肤代码和实现手段过于复杂,我把原作者的代码重新整理抽取出来,转换成Eclipse项目,重新整理成正确.可直接运行的项目. 代码运行结果如图. ...

  2. Android一键换肤功能:一种简单的实现

     Android一键换肤功能:一种简单的实现 现在的APP开发,通常会提供APP的换肤功能,网上流传的换肤代码和实现手段过于复杂,这里有一个开源实现,我找了一大堆,发现这个项目相对较为简洁:htt ...

  3. Android插件化的思考——仿QQ一键换肤,思考比实现更重要!

    Android插件化的思考--仿QQ一键换肤,思考比实现更重要! 今天群友希望写一个关于插件的Blog,思来想去,插件也不是很懂,只是用大致的思路看看能不能模拟一个,思路还是比较重要的,如果你有兴趣的 ...

  4. 网上找到的一个jquery版网页换肤特效

    这个跟我之前在锋利的JQuery那本书里看到的那个一模一样. <!DOCTYPE html> <html> <head> <meta name="& ...

  5. WPF 实现换肤功能

    将所有控件的基本样式汇集到一个资源字典中,构成界面的基本样式文件,然后进行不同颜色皮肤的定制. 即在新的皮肤资源字典文件中引入基本样式文件,然后使用资源继承,并且只设置控件的颜色属性等,形成一个皮肤文 ...

  6. Scss换肤

    项目中虽然没有一键换肤的要求,但是产品要求后期能换主题.在开发组件中涉及到主题的地方,要提取一些公用的变量,不要直接写死样式值.但是如果只是定义一些变量的话,只是完成控制颜色等值的提取.后期切换的话需 ...

  7. Android QMUI实战:实现APP换肤功能,并自动适配手机深色模式

    Android换肤功能已不是什么新鲜事了,市面上有很多第三方的换肤库和实现方案. 之所以选择腾讯的QMUI库来演示APP的换肤功能,主要原因: 1.换肤功能的实现过程较简单.容易理解: 2.能轻松适配 ...

  8. 一文读懂HarmonyOS服务卡片怎么换肤

    作者:zhenyu,华为软件开发工程师 关注HarmonyOS的小伙伴肯定对服务卡片已经很熟悉了.服务卡片(也简称为"卡片")是FA(FeatureAbility,元服务)的一种界 ...

  9. Android中插件开发篇之----应用换肤原理解析

    一.前言 今天又到周末了,感觉时间过的很快呀.又要写blog了.那么今天就来看看应用的换肤原理解析.在之前的一篇博客中我说道了Android中的插件开发篇的基础:类加载器的相关知识.没看过的同学可以转 ...

  10. 自定义一个JdbcTemplate(增删改数据库中表记录)

    需求: 自定义一个JdbcTemplate模板,实现增删改数据库中表记录的功能 1 package demo03; 2 3 import utils.JDBC_DBCP_Utils; 4 5 impo ...

随机推荐

  1. Google全球分布式数据库:Spanner

    2012年的OSDI上google发布了Spanner数据库.个人认为Spanner对于版本控制,事务外部一致性的处理,使用TrueTime + Timestamp进行全球备份同步的实现都比较值得一看 ...

  2. 吉特日化MES 与周边系统集成架构

    作者:情缘   出处:http://www.cnblogs.com/qingyuan/ 关于作者:从事仓库,生产软件方面的开发,在项目管理以及企业经营方面寻求发展之路 版权声明:本文版权归作者和博客园 ...

  3. nginx做白名单和限流

    ​ 在我们生产环境中使用到了地图服务,每个月有免费请求次数,近一个月请求次数突然暴涨,导致直接开启付费模式,一个月上百刀的花销着实难扛,根据实际我们的业务使用情况,远达不到付费标准,故考虑做白名单和限 ...

  4. python 中异常类型总结

    异常类型: 异常名称 描述BaseException             所有异常的基类SystemExit                   解释器请求退出KeyboardInterrupt  ...

  5. 【Unity3D】动态路障导航

    1 NavMeshObstacle组件 ​ 导航系统.分离路面导航中路障都是静态的,程序运行过程中烘焙的导航网格一直不变,本文将进一步讲解动态路障场景下导航的实现. ​ 对于动态路障游戏对象,除了要设 ...

  6. 【framework】Activity启动流程

    1 前言 ATMS启动流程 介绍了 ActivityTaskManagerService(ATMS)的启动和初始化流程,本文将介绍 Activity 的启动流程.由于 Activity 启动流程复杂, ...

  7. python第二章pta习题总结

    chapter2 一.选择填空判断部分 1. C语言中,变量变的是内存空间中的值,不变的是地址: Python中,变量变的是地址,不变的是内存空间中的值. 2. 3.bool('False') 的返回 ...

  8. 一键部署Home Assistant ubuntu 20.4.3 树莓派3b+脚本

      树莓派3b+安装好 Ubuntu Server 20.04.3 LTS 32bit 后即可适用此脚本,其他版本树莓派/系统可能需要微调脚本*为方便一些未知/已知错误排查 脚本存在冗余部分,足够了解 ...

  9. 【译】代码更快、更好,借助 GitHub Copilot 的新功能:斜杠命令和上下文变量

    你是否曾经希望有一个人工智能助手可以帮助你更快更好地编写代码?那就是 Visual Studio Copilot Chat 为您提供的:一个人工智能驱动的结对程序员,可以回答您的问题,建议代码片段,解 ...

  10. 详解SSL证书系列(1)什么是SSL证书?

    你一定遇到过这种情况,打开一个网站,浏览器弹出警告"您与此网站之间建立的连接不安全.由于此连接不安全,因此信息(如密码或信用卡)不会安全地发送到此网站,并且可能被其他人截获或看到" ...