vue + element-UI 实现深色模式和主题色动态切换

vue + element-UI 实现深色模式和主题色动态切换

首先说明一下,我对前端了解的不多,最近因为报的项目问题才临时学的vue(之前也用过一次),然后就套用了ruoyi-vue的板子,这是ruoyi项目源码的地址实现效果预览的地址,这篇文章主要只是给大家提供了一个思路,多半不会是最优解

前言

我看了ruoyi项目之后,感觉被它的可以切换主题色惊艳到了(当然其他也是,如代码生成,动态路由等等),但是它虽然做了深色模式,但是深色模式只涉及了菜单这一块,而主页内容却没有改变,且深色模式侵入到了各种vue代码中。我就产生了一些想法。

深色模式和主题色动态切换

这里的切换主要分成了三块:

  1. 本地样式的切换
  2. 主题色的切换
  3. element样式的切换

我在store中记录了theme和theme_color这两个值,我将深色模式视为一个主题,对应的也有标准和浅色模式,用theme来记录,theme_color记录的则是主题色
在这里插入图片描述
也就是ruoyi项目中对应的主题风格和主题颜色

本地样式切换

本地样式切换我用了一个比较阴间的实现方式,会导致所有与主题风格相关的样式(颜色)代码不得不写入到外部scss文件中,而不能直接写在vue文件内,会导致vue的scope特性无法发挥,使vue组件重用性的优点很大程度受到影响。

我的实现方式:

// 将#app的div的类型与theme绑定,在不同的域下面导入不同的主题颜色变量,
// 再导入需要这些变量的总体的样式文件
// app.scss
#app.theme-standard{
    
    
  @import "./theme/theme-standard";
  @import "app-base";
}

#app.theme-light{
    
    
  @import "./theme/theme-light";
  @import "app-base";
}

#app.theme-dark{
    
    
  @import "./theme/theme-dark";
  @import "app-base";
}
// theme-standard.scss
$menu-text:#bfcbd9;
$menu-active-text: #ffffff;
$sub-menu-active-text:#f4f4f5;//https://github.com/-eleme-f-e/element/issues/12951
$menu-bg:#404040;
$menu-hover:#263445;
$menu-focus:#152334;

// app-main.scss
.app-container{
    
    
  background: $app-bg;
}

这种玩法后患无穷,绝对不要试。 而且也无法导出变量给js使用。我写在这边完全是因为我真的为了想到这个花了好长时间,就算有问题还是难免想记录一下。

推荐的办法:

  1. 一种像ruoyi一样,导出其他样式的scss中的变量,vue文件中引用这些变量来进行设置,而且如果用了computed的话,代码上也不会特别难看
    <el-menu
    :background-color=
    	"settings.sideTheme === 'theme-dark' ? variables.menuBg : variables.menuLightBg">
    </el-menu>
    <
    
  2. 链接

主题色切换

主题色的实现方式

  1. 申请新的element样式,替换掉该主题色的值,写入到style中
  2. 从App.vue中设置color为主题色,这样后续就可以使用currentColor来设置颜色

首先可以看一下 element返回的样式,里面默认的主题色是#409EFF,只要换成我们要的主题色就行了。

但是还有一个问题,element-ui有很多hover,active时会有基于主题色变淡的颜色还有阴影色等。

这就得看element是如何生成这些颜色的,总的来说:

  1. 10级向浅色渐变
  2. 0.9倍阴影色
// 浅色渐变方法
tintColor = (color, tint) => {
    
    
	red += Math.round(tint * (255 - red))
	green += Math.round(tint * (255 - green))
	blue += Math.round(tint * (255 - blue))
	return `#${
      
      red}${
      
      green}${
      
      blue}`
}
// 阴影色方法
shadeColor = (color, shade) => {
    
    
    red = Math.round((1 - shade) * red)
    green = Math.round((1 - shade) * green)
    blue = Math.round((1 - shade) * blue)
    return `#${
      
      red}${
      
      green}${
      
      blue}`
// 生成颜色集群
for (let i = 0; i <= 9; i++) {
    
    
        clusters.push(tintColor(theme, Number((i / 10).toFixed(2))))
      }
      clusters.push(shadeColor(theme, 0.1))
}
// 替换掉所有 #409EFF 生成的cluster 成 我们要的主题色生成的cluster
let newStyle = style
oldCluster.forEach((color, index) => {
    
    
  newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index])
})
// 写入到样式中
let styleTag = document.getElementById(id)
if (!styleTag) {
    
    
	 styleTag = document.createElement('style')
	 styleTag.setAttribute('id', id)
	 document.head.appendChild(styleTag)
}
styleTag.innerText = newStyle

element样式切换

这是ruoyi没有做的,因为没有修改element背景色之类的需求,如果我们要做深色模式就得修改element的颜色。

然后我们就得定制样式文件,但是我的办法貌似并不是element推荐的。。。

办法就是修改刚才的element样式,定制出各个主题版本,主要修改背景色、边框颜色和字体颜色
效果大概是
在这里插入图片描述
但是可能会出现这种突然特别亮的阴间配色,这些颜色会出现在10级浅色渐变,默认的10种颜色就是

[
    "409EFF",
    "64,158,255",
    "#53a8ff",
    "#66b1ff",
    "#79bbff",
    "#8cc5ff",
    "#a0cfff",
    "#b3d8ff",
    "#c6e2ff",
    "#d9ecff",
    "#ecf5ff",		// 这个注意一下噢
    "#3a8ee6"
]

只要在这10种颜色中找出,切换成灰色就可以比较ok了,其实还是有点阴间。。。看大家配色的功夫了。。。
在这里插入图片描述

总结

我主要想讲的就是如何动态切换主题的,实现方式是请求样式文件,多半是会一定程度上导致白屏。。。反正就是这样,我就提供一个思路啊

猜你喜欢

转载自blog.csdn.net/weixin_44815852/article/details/115387947