老h5项目动态换主题颜色的快速集成方案 | 创作者训练营

2,149 阅读4分钟

源起

最近遇到一个老的h5项目需要动态换主题颜色的需求,所谓动态换主题色,就是页面需要在运行的时候,根据一些条件来更换颜色,而不是在编译的过程中就把颜色打包进去的静态更换颜色。我们这个项目是react+less的,之前用Less的变量做过静态的更换颜色。今天也是突然遇到这个问题,并且时间比较急,最后也是花了几个小时来解决这个问题。

难点在哪?

  1. 是老项目的问题,这个页面连色值的变量都没替换,还是每个地方都用的是色值。首先就是要统一的替换这些色值变为颜色的变量。而且需要进行一些整理还要注意不能影响老的样式不能错。所以在行内直接用变量判断使用不同的class或者样式的方法开始先搁置了,想用一个侵入性比较小方案。
  2. 是要做成动态的变色,在打包的时候,更改色值,是可以做的。但是要在runtime动态更改颜色,一开始没想到特别好也侵入性比较小的方案。

一些失败的尝试

我最开始搜索一些方案,发现less.js(是的,我也是今天才知道less还有js的工具),中其实是有个方法(less.modifyvars)来动态更改less的变量的。当然首先遇到的问题就是不生效。一开始怀疑是页面的生命周期的问题,所以就把modifyvars方法更改了几个生命周期,发现都不生效。后面发现less.js报出一个错误,是说没有读取到样式文件。经过查询,是说要把less文件用link标签在html页面中引用,才能被读取到。所以我就把放变量的less文件整个上传到了七牛上,然后通过link标签引用这个theme.less。引用后发现,在less的文件中,是读取的不到这些颜色的变量的,会报错。这时候这条路就感觉走不通了。

之后又找过一些webpack的插件,比如有一个叫'switch theme'的webpack插件。这个插件需要把样式文件按照它的方式放到指定的目录下,并且需要另外的loader才能够生效。它提供了一个js的方法去动态的更改颜色。但是觉得这个改动还是比较大,需要更改webpack的配置,而且本身我们在less-loader和css-loader也有一些根据不同页面的定制化配置,也不是很好的集成,所以这个方案也暂时放弃了。

快速集成的方案

花了两三个小时的查资料与折腾后,读到了一篇大佬的文章:《史上最简单的ant-design的换肤方案》,他的思路是使用css变量,在更改颜色的时候,通过js创建一个style标签,把这些颜色的变量更新。

下面是一些关键代码,可以让你快速了解css变量 less 文件:

:root { // css变量放在:root--theme-color:red;// 这里定义一个css变量
}

div.selected {
    color: var(--theme-color); // 通过var()来使用这个变量
}

js文件

const cssVar = `
  :root {
      --primary-color: green;// 这里是要更改的颜色
  }
`;

styleNode = document.createElement('style'); // 创建一个style 标签

styleNode.innerHTML = `${cssVar}`; // style标签中包含更改的css变量的内容
document.getElementsByTagName('head')[0].appendChild(styleNode); // 把这个style标签放在header中,这样更换的颜色就生效了

mdn上有介绍css变量的,想要深入了解的可以自行查阅。

兼容性怎么样?

可能各位会担心css变量的兼容性,这里附上caniuse的截图 其实大部分浏览器是已经支持了,覆盖率在94.5%。

之后的探索

  1. 其实ant.design是实现了动态更改主题颜色的。ant.design也有一些webpack插件可以更改ant.design中的主题色。我希望之后有时间的话可以学习一下ant.design是怎么实现的。

  2. 可以探索一下css变量的一些灵活的使用,不仅仅局限于改变颜色

这是我2021年更30篇文的第2篇,进度2/30

文章标题XXX | 创作者训练营 征文活动正在进行中......