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

Posted 林恒

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了记录--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>;中显示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">

vue2.0-基于elementui换肤[自定义主题]

0. 直接上 预览链接

vue2.0-基于elementui换肤[自定义主题]

1. 项目增加主题组件

在项目的src/components下添加skin文件夹

skin文件获取地址

2. 项目增加自定义主题

自定义添加主题下载地址 https://elementui.github.io/theme-chalk-preview/#/zh-CN

3. 项目引入和使用

技术分享图片

选择你想要随主题改变的element元素在src/global/themeArray里面,不希望随主题改变的可以注释掉

技术分享图片

选择皮肤之后把记录存在cookie里面。

技术分享图片

再次打开浏览器访问项目钩子初始化的时候从cookie里面得到之前选择的皮肤。

技术分享图片

至此整合完毕 源码地址

Vue学习大佬群493671066,美女多多。老司机快上车,来不及解释了。

作者相关Vue文章

基于Vue2.0实现后台系统权限控制

前端文档汇总

VUE2.0增删改查附编辑添加model(弹框)组件共用

打赏 衷心的表示感谢

技术分享图片

以上是关于记录--Vue3自定义一个Hooks,实现一键换肤的主要内容,如果未能解决你的问题,请参考以下文章

在 react 里写 vue3 ? 还写了自定义 hooks和 Hoc 构建了响应式 !

QML工程化应用之一键换肤

stylish——一键为网页换肤,改变字体大小,去除广告

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

Android一键换肤原理简述

Android一键换肤原理简述