翼度科技»论坛 编程开发 html5 查看内容

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

6

主题

6

帖子

18

积分

新手上路

Rank: 1

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



核心


  • 使用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)下的样式
两套样式代码大概如下(列了一部分):
  1. :root {
  2.   --color-body-bg: #ffffff;
  3.   --color-text: #000;
  4.   --color-secondary-bg-for-transparent: rgba(209, 209, 214, 0.28);
  5. }
  6. html[data-theme='dark'] {
  7.   --color-body-bg: #222222;
  8.   --color-text: #ffffff;
  9.   --color-primary-bg-for-transparent: rgba(255, 255, 255, 0.12);
  10. }
复制代码
然后我们点击的时候,通过
  1. let theme = 'light'            // light / dark  
  2. document.documentElement.setAttribute('data-theme', theme)
复制代码
这样就能实现简单的更换肤色功能了
什么? 你以为这就完了?好戏刚开始
跟随系统颜色

首先利用Window 的 'matchMedia()' 方法返回一个新的 MediaQueryList 对象,表示指定的媒体查询 (en-US)字符串解析后的结果。
如运行媒体查询(max-width: 600px)并在;中显示MediaQueryList的matches属性值。如果视口的宽度小于或等于 600 像素,则输出将为 true,而如果窗口的宽度大于此宽度,则将输出 false。
  1. [/code][code]let mql = window.matchMedia('(max-width: 600px)');
  2. document.querySelector(".mq-value").innerText = mql.matches; //此时小于或等于600像素时span 里面的结果为false
复制代码
利用prefers-color-scheme [CSS媒体特性] 用于检测用户是否有将系统的主题色设置为亮色或者暗色。
  1. .day   { background: #eee; color: black; }
  2. .night { background: #333; color: white; }
  3. @media (prefers-color-scheme: dark) {
  4.   .day.dark-scheme   { background:  #333; color: white; }
  5.   .night.dark-scheme { background: black; color:  #ddd; }
  6. }
  7. @media (prefers-color-scheme: light) {
  8.   .day.light-scheme   { background: white; color:  #555; }
  9.   .night.light-scheme { background:  #eee; color: black; }
  10. }
复制代码
两者相结合

把matchMedia()和prefers-color-scheme 结合在一起, 我们就可以通过 js 去给系统颜色为dark或 light 的情况下更换对应的 html自定义属性, 即[data-theme='dark']或 [data-theme='light']
首先,我们先去获取主题颜色, 我们还没设置的时候,就默认是系统颜色, 设置了就把他存储起来,下次直接获取这个颜色
  1. // 获取主题变量
  2. let appearance = ref<string>(localStorage.getItem('appearance') || 'auto')
  3. // 查询当前系统主题颜色
  4. const match = window.matchMedia("(prefers-color-scheme: dark)")
  5. // 如果主题变量为 auto, 则跟随系统主题
  6. if (appearance.value === 'auto') {
  7.     followSystem()
  8. } else {
  9.     document.documentElement.setAttribute('data-theme', appearance.value)
  10. }
  11. function followSystem() {
  12.     // 当前系统颜色是亮色还是暗色 , 设置对应的html[data-theme= 'dark' 或者'light']
  13.     const theme = match.matches ? 'dark' : 'light'
  14.     document.documentElement.setAttribute('data-theme', theme)
  15. }
  16. // 监听系统主题变化,电脑主题发生改变的时候就调用followSystem函数
  17. match.addEventListener('change', followSystem)
复制代码
封装成一个hooks

暴露出一个 useThemeColor函数, 返回一个对象, 对象里面返回我们的主题变量
  1. / 获取主题变量
  2. let appearance = ref<string>(localStorage.getItem('appearance') || 'auto')
  3. // 查询当前系统主题颜色
  4. const match:MediaQueryList = window.matchMedia("(prefers-color-scheme: dark)")
  5. // 监听系统主题变化
  6. match.addEventListener('change', followSystem)
  7. function followSystem() {
  8.     const theme = match.matches ? 'dark' : 'light'
  9.     document.documentElement.setAttribute('data-theme', theme)
  10. }
  11. watchEffect(() => {
  12. // 如果主题变量为 auto, 则跟随系统主题
  13.     if (appearance.value === 'auto') {
  14.         followSystem()
  15.     } else {
  16.         document.documentElement.setAttribute('data-theme', appearance.value)
  17.     }
  18. })
  19. export default function useThemeColor() {
  20.     return {
  21.         appearance,
  22.     }
  23. }
复制代码
使用hooks

导入我们export出来的函数
  1. import useThemeColor from '../hooks/useThemeColor'
复制代码
使用函数,注意, 这里返回的 apprance 已经是一个响应式数据了
  1. const { appearance } = useThemeColor()
复制代码
使用 v-model 绑定apprance,直接使用apprance , 当我们切换颜色的时候, 就会调用watchEffect里面的函数, 达到一键换肤效果
[code]               外观                                {{ "自动" }}            
来源:https://www.cnblogs.com/smileZAZ/p/17444051.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具