首页 > 其他分享 >记录--Vue3自定义一个Hooks,实现一键换肤

记录--Vue3自定义一个Hooks,实现一键换肤

时间:2023-05-30 18:22:07浏览次数:60  
标签:换肤 自定义 -- light appearance dark color theme data

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

核心

  • 使用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">

标签:换肤,自定义,--,light,appearance,dark,color,theme,data
From: https://www.cnblogs.com/smileZAZ/p/17444051.html

相关文章

  • OpenCV 和 TensorRT 之间的数据转换 HWC to CHW
    TensorRT做图像相关模型部署的时候,导入图片的数据存储往往是BHWC(Batch,Height,Width,Channel),而TensorRT推理的时候是BCHW.OpenCV和TensorRT之间的数据转换(BHWCtoBCHW),一般是所有元素遍历赋值:cv::Matorigin_image=cv::imread("test.jpg",1);if(!orig......
  • C3P0的使用实例
    当然,以下是一个详细的C3P0示例代码,演示了如何配置和使用C3P0连接池:importcom.mchange.v2.c3p0.ComboPooledDataSource;importjava.beans.PropertyVetoException;importjava.sql.Connection;importjava.sql.PreparedStatement;importjava.sql.ResultSet;importjava.sq......
  • mysql执行优化器
    sql这个ql看着给人感觉t表是驱动表,其实优化器优化后trc才是驱动表,因为t的查询条件筛选出来有50多万,二trc筛选只有几千条explainselectdistinctt.`id`as"id",t.deletedas"deleted",t.noas"no",ru.nameas"requester_name",tm.solve_minutesas"ticketMetric......
  • Excel 中的OFFSET、MATCH 和 HLOOKUP的函数介绍
    OFFSET、MATCH和HLOOKUP是Excel中常用的三个函数,它们的功能分别如下:1.OFFSET函数:根据指定的行列偏移量,从某个单元格开始返回一个新的单元格区域,可以用于提取数据区域内部特定的行或列,或者将数据区域向右或向左平移。2.MATCH函数:在某个区域或列表中查找指定的值,并返回其......
  • VMware 供外网访问
    配置过程一、首先配置VMware的“虚拟网络设置”。二、“更改设置”三、vm信息设置为“桥接模式”如果没有VMnet0点击左下角还原默认设置 就会出现四、设置vmware安装系统的网络模式五、网络适配器-->网络链接设置为“桥接模式” ......
  • MyCat使用实例
    MyCat是一个开源的数据库中间件,用于实现数据库分片和读写分离。它并不提供JavaAPI来编写应用程序,而是作为一个代理服务器,将应用程序的数据库请求转发到底层的数据库服务器。在Java应用程序中使用MyCat并没有特定的代码示例,因为MyCat本身并不提供JavaAPI。您可以按照以下步骤来......
  • CentOS7系统打包ISO镜像_超详细
    CentOS系统打包ISO镜像DIY自己的IOS镜像使用工具:Linux系统、Mondo1.前置工作2.安装mondorescue3.修改mondo配置4.将系统的硬盘挂载从UUID挂载方式改为盘符挂载的方式5.root用户执行mondoarchive6.选择备份位置7.选择备份路径8.压缩类型选择9.压缩率选择10.设置ISO镜像的大小......
  • python day6
    第一阶段第六章6.1数据容器 6.2列表列表中元素类型不限,可以混合 ["itheima",888,True]1#列表里面嵌套列表2my_list=[[1,2,3],[4,5,6]]3print(my_list)4print(type(my_list))6.3列表遍历下标定义可以反向 #列表里面嵌套列表取数据my_......
  • Elasticsearch专题精讲—— 操作文档 ——读写文档
     操作文档——读写文档1、Introductionhttps://www.elastic.co/guide/en/elasticsearch/reference/8.8/docs-replication.htmlEachindexinElasticsearchisdividedintoshardsandeachshardcanhavemultiplecopies.Thesecopiesareknown......
  • 智慧档案室八防十防建设平台之监控室硬件产品配置清单
    ​智慧档案馆八防十防环境建设平台所需配置清单之监控室所需硬件产品配置表      序号名称型号品牌单位数量1工业控制主机订制盛世宏博套1.00 2显示屏X23E1HAOC台1.00 3数字化智慧档案馆物联网综合一体化建设平台V1.0V1.0盛世宏博......