最近公司项目中有一个需要更换web端主题的需求,基本实现效果如下:

接收到这个需求的时候有三种思路:

  • 打包的时候同时冗余打包多套CSS文件,并在切换主题的时候加载相应的样式文件。
  • 在根组件上加上主题类名,并在切换主题的时候改变类名,然后通过CSS类来覆盖已有样式。
  • 利用 antd-theme-webpack-plugin将less文件加载,并在线解析less文件后覆盖已有CSS
  • 线上解析所有样式代码,并根据新的颜色重新生成样式,并加入HTML中 下面逐个方案分析:

方案一:打包的时候同时冗余打包多套CSS文件

劣势相当明显,第一是打包速度严重拖慢,第二是切换主题的时候还需要重新从服务器上获取CSS文件,意味着切换个主题需要等上好几秒之后才能见效。优势的话,估计就是实现起来稍微简单一点了。但这个很明显不是我想要的结果。

方案二:在根组件上加上主题类名

优势在于切换成本比较低,但是劣势也比较明显:第一是打包体积严重增加(多加一套主题样式文件几乎增加一倍),第二是后续代码维护困难,需要把所有需要更换主题的样式文件全部写进所有主题类里面,工作量太大,而且是个无底洞。

方案三:利用 antd-theme-webpack-plugin

这套方案的可以根据antd里面的所有less文件中的变量进行替换,正好我们的项目又是基于Reactantd,简直完美融合。于是欣然试用,最终试用结果是:我水土不服了。做个简单的demo的时候运行很好,没问题,但是移植到已有项目的时候就出现各种不适应,首先是版本问题,这个好解决。然后又出现其他报错,一个一个解决完了之后发现实际运行起来之后还是水土不服。

另外这种模式还有另外的劣势,必须额外加载less文件,并且在线上解析所有less文件,然后应用到DOM中,对于我们这个光是样式文件打包(还是minify之后的)起来都有1M左右的项目来说简直是灾难。

方案四:线上解析所有样式代码

这种方案其实是比较讨巧的做法,将所有的linkstyle标签的样式取出来,然后替换相应的变量,再注入到DOM节点中,完成样式替换。不需要太多额外的文件引入,是一个比较好的实现思路,唯一的问题就在于前面提到的1M多的样式文件,考虑到本身项目已经比较庞大,在加上这么大的额外开销还是忍痛拒绝了。

于是主题到了:并非所有的样式代码都需要解析的,因为毕竟换肤一般来说只会更换一两个颜色,而不会更换所有的样式文件,那么何不在发布线上之前就将CSS解析好,线上的时候只需要解析这些已经处理好的样式文件即可,实际操作下来之后1M左右的样式文件只需要处理几KB的数据。在实际线上运行之后发现也确实比较流畅,也就是文章开头的GIF的效果了。

这个方案灵感来源于 webpack-theme-color-replacer,该项目通过webpack插件形式将样式文件解析后将更换主题的代码注入到每个js头部,实现思路很漂亮,只是看了代码之后有几个问题:

  • 样式加载到每个js头部,冗余!
  • 颜色匹配必须对应array中的顺序,而且不直观
  • 需要额外再代码中引入样式替换的js

综合起来觉得使用起来比较繁琐,于是自己动手撸了一个webpack插件:webpack-stylesheet-variable-replacer-plugin,只需要在webpack配置中增加一个plugin,其他的就OK了,支持key--value方式来定义需要替换的变量,还有就是注入文件可控,不会重复注入。下面介绍一下使用方法,简单三步走:

  • 引入插件
const WebpackVariableReplacer = require('webpack-stylesheet-variable-replacer-plugin');

  • 定义插件配置信息
new WebpackVariableReplacer({publicPath: '',buildPath: 'static/',nextSupport: true,specifyEntry: /_app.js/,matchVariables: {main: '#209CEE',}}),

  • 客户端调用替换主题的方法:
window.replaceStyleVariable && window.replaceStyleVariable({main: color});

运行效果还是看文章开头的GIF,总结来说,效率高,代码侵入性低,方便使用。理论上来说,在angular和vue中使用也没有任何问题。不过本人主要技术栈还是react,其他没有测试。 知乎竟然不支持表格,想要看参数直接去我的博客上去看吧: eaTong个人站 https://eatong.cn/blog/3

js变量传递给less_如何利用webpack实现一键换肤(CSS变量替换)相关推荐

  1. 如何利用 SCSS 实现一键换肤

    本文首发于政采云前端团队博客:如何利用 SCSS 实现一键换肤 https://www.zoo.team/article/theme-scss 前言 在项目开发过程中,我们有时候遇到需要更换站点主题色 ...

  2. rails 共享变量_如何将Rails实例变量传递给Vue组件

    rails 共享变量 by Gareth Fuller 由Gareth Fuller 如何将Rails实例变量传递给Vue组件 (How to pass Rails instance variable ...

  3. vb ajax提交post,使用jQuery AJAX将JS数组传递给VB.Net post

    我使用jQuery AJAX post请求将客户端JS数组传递给服务器端VB.NET代码.我有一种方法可行,但我想知道最佳做法.我一开始是这样的:使用jQuery AJAX将JS数组传递给VB.Net ...

  4. [CSS] 自定义变量带你随心所欲,一键换肤

    认识CSS自定义变量 CSS自定义属性?听着怎么那么神奇呢,属性还可以自定义,那不是可以放肆地玩耍?我自己定义的属性浏览器都能认识? 一.基础 (一)名字和用途 其实CSS自定义属性还有很多小名,比如 ...

  5. vue中利用scss实现整体换肤和字体大小设置

    一.前言 利用Sass预处理实现换肤和字体大小调整. 思路及达到的效果:字体大小的适配使用window.devicePixelRatio的值和需要调整的差量进行控制.页面初始化是的字体适配可以根据de ...

  6. java程序中执行maven_java – 将一个enviornment变量传递给Maven中的已执行进程

    我一直在墙上撞了大约一个小时:我正试图将一个简单的属性( java.library.path)传递给exec-maven-plugin.目标是将其与Netbeans右键单击文件集成>运行文件过程 ...

  7. java变量传递给asp,我应该如何将多个参数传递给ASP.Net Web API GET?

    回答(10) 2 years ago 这个记录标记是什么意思?如果这仅用于记录目的,我将使用GET并禁用所有缓存,因为您要记录此资源的每个查询 . 如果记录标记有另一个目的,POST就是要走的路 . ...

  8. 如何把js变量传递给html页面,如何将js变量从一个html文件传递给另一个?

    我的问题很简单,但由于我仍然缺乏合并js,php和html的熟练程度,因此无法找到解决此问题的解决方案. 问题涉及3个文件:如何将js变量从一个html文件传递给另一个? JS1.js functio ...

  9. php获取form传递的变量,PHP-将变量传递给Ninja Form字段

    目的 以下函数应使用变量在我的表单上预填充隐藏字段(hidden_​​email -). 怀疑 但是,在加载页面时已经声明了我需要传递给该字段的变量" $cust_email".现 ...

最新文章

  1. Openresty最佳案例 | 第9篇:Openresty实现的网关权限控制
  2. 系统制成docker镜像_如何让Docker基础镜像变得更小?
  3. 表格行上下移,置顶的js代码
  4. oracle软件 乱码,oracle 中文乱码解决办法
  5. 将一个数组划分成总和相等的两部分
  6. 计算机网络常见简答题
  7. 关于C51中“大小端存储”问题的详解
  8. TM4C123GLaunchPad教程四_时钟配置
  9. 图灵测试其实已经过时了
  10. mysql超卖问题处理_高并发下超卖问题及如何解决
  11. jsp之${CTX}理解
  12. 2021-1-30最短路入门
  13. html压缩工具html-minifier -- nodejs常用模块(4)
  14. iscoll.js卡顿问题
  15. Echarts中DataView显示Excel表格
  16. 圣地亚哥大学计算机科学专业,加州大学圣地亚哥分校计算机科学与工程系
  17. java list集合包含_Java 中的集合类包括 ArrayList 、 Linke
  18. KMP算法求循环节,为什么能求循环节
  19. 三全食品安全阴云未散:京东自营店未公示生产许可证
  20. Oracle取小数点部分

热门文章

  1. NBT:牛瘤胃微生物组的4941个宏基因组组装基因组(MAG)
  2. Nature子刊:南土所贾仲君组-稻田甲烷氧化的微生物机制
  3. 小麦的一生矢量图收藏贴-从种子的萌发到完熟
  4. pandas将dataframe中的特定数据列的内容转化为列表list数据(convert dataframe column values into a list)
  5. python使用matplotlib可视化subplots绘制子图、自定义几行几列子图,如果M行N列,那么最终包含M*N个子图、在指定的子图中添加可视化结果
  6. R语言ggplot2可视化:使用scale_y_continous函数自定义指定Y轴的坐标范围以及对应的数值、将坐标轴的数值设置为需要的数据类型(整型、浮点型)
  7. R语言gganimate包创建可视化gif动图、可视化动图:ggplot2可视化静态散点图、gganimate包创建动态散点分面图(facet_wrap)动画基于transition_time函数
  8. python使用imbalanced-learn的RandomUnderSampler方法进行下采样处理数据不平衡问题
  9. plotly可视化绘制多坐标轴图
  10. ModuleNotFoundError: No module named ‘scipy.spatial.transform._rotation_groups‘