3.2 Browser -- useColorMode

ops/2024/9/23 4:27:20/

3.2 Browser – useColorMode

https://vueuse.org/core/useColorMode/

作用

可以自动持久化的响应式颜色主题模式。

官方示例

import { useColorMode } from '@vueuse/core'const mode = useColorMode() // Ref<'dark' | 'light'>

默认情况下,它将使用usePreferredDark(又名自动模式)与用户的浏览器首选项匹配。

当读取ref时,它将默认返回当前的颜色模式(暗,亮或您的自定义模式)。

通过启用emitAuto选项,可以将自动模式包含在返回的模式中。

当写入ref时,它将触发DOM更新并将颜色模式持久化到本地存储(或您的自定义存储)。你可以传递auto来设置回自动模式。

mode.value // 'dark' | 'light'mode.value = 'dark' // change to dark mode and persistmode.value = 'auto' // change to auto mode
  • 配置
import { useColorMode } from '@vueuse/core'const mode = useColorMode({attribute: 'theme',modes: {// 自定义模式,默认为'dark' | 'light'dim: 'dim',cafe: 'cafe',},
}) // Ref<'dark' | 'light' | 'dim' | 'cafe'>
  • 组件用法。

提供了非渲染组件,代码在@vueuse/components包中。

<UseColorMode v-slot="{ mode }"><button @click="mode = mode === 'dark' ? 'light' : 'dark'">Mode {{ mode }}</button>
</UseColorMode>

源码分析

代码地址:https://github.com/vueuse/vueuse/blob/main/packages/core/useColorMode/index.ts。

这个函数主要有两个用处:

  1. 获取当前的颜色模式
  2. 修改当前的颜色模式
  • 先看第一步:初始化颜色模式,优先级是 存储 > 用户传递,同时监听模式变化。
export function useColorMode<T extends string = BasicColorSchema>(options: UseColorModeOptions<T> = {}) {const {selector = 'html',attribute = 'class',initialValue = 'auto',window = defaultWindow,storage,storageKey = 'vueuse-color-scheme',listenToStorageChanges = true,storageRef,emitAuto,} = optionsconst modes = {auto: '',light: 'light',dark: 'dark',...options.modes || {},} as Record<BasicColorSchema | T, string>// 1 判断浏览器的默认模式是不是dark模式const preferredDark = usePreferredDark({ window })const preferredMode = computed(() => preferredDark.value ? 'dark' : 'light')/*** 2 如果用户传递了storageRef,直接使用*   如果没传,看storageKey == null是否成立,因为有默认值,所以一般不成立*   那么就会从storage中取值,根据useStorage的用法,如果localStorage中有值,直接返回localStorage中存储的值;*   如果没有,使用默认值'auto',并且写入localStorage*   在这里store = 'auto'*/const store = storageRef || (storageKey == null? ref(initialValue) as Ref<T | BasicColorSchema>: useStorage<T | BasicColorSchema>(storageKey, initialValue as BasicColorSchema, storage, { window, listenToStorageChanges }))/*** 3 state的结果和preferredMode以及store都有关系。*		也就是浏览器默认模式变化(比如19点钟由light变成了dark),以及用户在其他地方修改了localStorage中值,都会影响state。*		preferredMode 和 store的响应式,由 usePreferredDark和 useStorage这两个 hook来维护*/const state = computed<T | BasicColorSchema>({get() {// 如果!emitAuto,那么默认就是浏览器的首选项,也就是说不存在'auto'这个选项return store.value === 'auto' && !emitAuto? preferredMode.value: store.value},set(v) {store.value = v},})// ....../*** 4 监听state的变化,回调onChanged方法。*/watch(state, onChanged, { flush: 'post', immediate: true })if (emitAuto)watch(preferredMode, () => onChanged(state.value), { flush: 'post' })// 5 如果是在组件中调用,那么在 onMounted钩子中执行 onChangedtryOnMounted(() => onChanged(state.value))return state
}
  • 再看第二步,当state变化了,触发onChanged回调。

这里可以引起变化的操作包括:

  1. 用户主动修改
  2. 颜色模式跟随系统变化
  3. localStorage中存储的模式发生了变化
/**
* 1 watch 触发了 onChanged方法,onChanged调用了 defaultOnChanged
*/ 
function onChanged(mode: T | BasicColorSchema) {if (options.onChanged)options.onChanged(mode, defaultOnChanged)elsedefaultOnChanged(mode)}/**
* 2 看一下上面的默认值,假设 resolvedMode是 dark
*   这个函数的意思是:把 html的 class改成 'dark'
*/
function defaultOnChanged(mode: T | BasicColorSchema) {const resolvedMode = mode === 'auto' ? preferredMode.value : modeupdateHTMLAttrs(selector, attribute, modes[resolvedMode] ?? resolvedMode)
}// 不用管这个函数,简单地认为是执行回调函数即可
const updateHTMLAttrs = getSSRHandler('updateHTMLAttrs',(selector, attribute, value) => {const el = window?.document.querySelector(selector)if (!el)return/*** 3 接下来逐行解释一下*/ if (attribute === 'class') {// 以空格分割value,因为value是类名,所以是空格分割。在这里 current = ['dark']const current = value.split(/\s/g)Object.values(modes)                     // ['', 'light', 'dark', 'dark contrast', 'cafe'].flatMap(i => (i || '').split(/\s/g))  // ['', 'light', 'dark', 'dark', 'contrast', 'cafe'].filter(Boolean)                       // ['light', 'dark', 'dark', 'contrast', 'cafe'].forEach((v) => {if (current.includes(v))               // eg: if(['dark'].includes(light))el.classList.add(v)                  // classList 增加最新的 classelseel.classList.remove(v)               // classList 删除以前设置过的 class})}else {el.setAttribute(attribute, value)}})

http://www.ppmy.cn/ops/105024.html

相关文章

Spel注入漏洞分析

文章目录 SPEL注入SPEL漏洞案例CVE-2022-2297EXP SPEL注入 SPEL是Spring框架中的一种表达式语言&#xff0c;用于在Spring配置中动态计算值。它提供了一种简洁的语法&#xff0c;用于访问和操作对象的属性、调用方法、进行数学计算、逻辑运算等。允许开发者在Spring应用程序中…

Java基于微信小程序的超市购物管理系统

1 简介 Java基于微信小程序的超市购物管理系统&#xff0c;此超市购物系统利用当下成熟完善的springboot框架&#xff0c;使用跨平台的可开发大型商业网站的Java语言&#xff0c;以及最受欢迎的RDBMS应用软件之一的Mysql数据库进行程序开发。实现了收货地址管理、购物车管理、…

JVM(Java虚拟机)

Java的“一次编写&#xff0c;处处运行”主要得益于Java的设计理念和Java虚拟机&#xff08;JVM&#xff09;的存在。 JVM&#xff08;Java Virtual Machine&#xff09;是Java虚拟机的简称&#xff0c;它是运行所有Java程序的抽象计算机。也就是说&#xff0c;JVM是一个能够运…

世界复合医学杂志社世界复合医学编辑部2024年第4期目录

论著 苏子降气汤联合三子养亲汤治疗痰浊壅肺型慢性阻塞性肺疾病急性加重期的临床疗效 周芹;周磊; 1-437 天麻钩藤汤加减联合依那普利叶酸片对原发性高血压患者血压水平与中医证候积分的影响 邹文博;王世雄; 5-8 伏诺拉生联合康复新液治疗反流性食管炎的临床研究 孙…

浅谈安科瑞系能源配套产品在美特新材料光储充一体化项目上的应用

项目背景&#xff1a; 项目名称&#xff1a;湖南美特新材料科技有限公司光储充一体化项目工程总承包&#xff08;EPC&#xff09; 建设地点&#xff1a;长沙市望城经济技术开发区腾飞路二段568号 建设规模和主要内容&#xff1a; 建设规模:储能装机容量7.5MW/16.054MWh&#x…

如何在忘记密码或 ID 的情况下解锁 iPhone 15

您是否曾经因为忘记了 iPhone 密码而陷入困境&#xff0c;或者您是否多次错误地输入了屏幕时间密码并发现自己被锁定在 iPhone 之外&#xff1f; 被锁定和拒绝访问您的 iPhone 可能很常见&#xff0c;尤其是在您尚未配置 Face ID 的情况下。或者&#xff0c;如果 Face ID 无法正…

c++ vector的用法

std::vector 是 C 标准库中一个非常常用的动态数组容器。它可以存储任意数量的元素&#xff0c;并且提供了灵活的大小调整和对元素的快速访问。以下是 std::vector 的基本用法说明&#xff0c;包括常见操作和示例代码。 1. 头文件 在使用 std::vector 之前&#xff0c;需要包…

云计算day37

使⽤docker部署project-exam-system 1. 背景&#xff0c;在⼀台主机之内&#xff0c;实现容器的编排&#xff0c;发布考试系统 2. 环境准备 1. docker 1. vim /etc/docker/daemon.json 2. docker-compos 3. 普通的部署 1. 镜像 1. 前端&#xff1a;nginx latest服务 1…