antd 换肤方案

需求分析

现有方案缺陷

  • CSS 变量

无法支持复杂表达式 mix(var(–primary-color), #fff, 20%)
浏览器兼容性有限(ie 不支持)

  • 多套 CSS 主题

主题样式固定,无法实时切换主题色
CSS 代码分离不好处理

  • less 动态切换

需要引入 less runtime 体积较大
切换主题时会对整个样式表进行 parse -> eval -> genCSS 处理,导致切换速度很慢

想要实现的目标

  • 支持实时修改 @primary-color, @border-radius-base 之类的参数
  • 浏览器页面刷新后默认就是切换后的样式,没有多余的动画、明显的加载过程
  • 打包体积小,无需打包多个样式文件
  • 代码分离友好,不同页面的样式可以分别加载

实现方案

方案一

  • 原理:通过类覆盖的方式来动态修改颜色,因为 CSS 加载机制是由上至下,同名会覆盖对应属性。

  • 开源实现:dynamic-antd-theme github.com/luffyZh/dyn…

  • 评论:做了很多重复大量的 css 操作来覆盖类名,只做了@primaryColor 相关的覆盖,其他覆盖仍然需要:global 或者组件内覆盖这种方式。有现成的即插即用换肤插件,直接使用。

方案二

  • 原理:编译时把不同皮肤需要修改的 less 变量、表达式留空, 在运行时填充。

  • 开源实现:antd-theme github.com/wuzekang/an…

  • 评论:开箱即用。存在限制:

1、postcss-position 不兼容。
postcss-position 会直接对 css 中的 position 属性值进行 value.match(/^static|absolute|fixed|relative…/).toString(),而 ‘”[theme:position,default:relative]”‘.match(…) === null
因此会出现在编译过程中的报错,具体的 postcss-position 代码在这里: github.com/seaneking/p…
2、递归 Mixin Call 的循环变量不能作为皮肤变量, 比如 ant-design 栅格系统相关代码中的 @grid-columns

.loop-grid-columns(@index, @class) when (@index > 0) {
  .@{ant-prefix}-col@{class}-order-@{index} {
    order: @index;
  }
  .loop-grid-columns((@index - 1), @class);
}

.loop-grid-columns(@grid-columns, @class);
复制代码

方案三

  • 原理:通过 webpack 插件形式将样式文件解析后将更换主题的代码注入到每个 js 头部。

  • 开源实现:webpack-theme-color-replacer github.com/hzsrc/webpa…

  • 评论:需要额外再代码中引入样式替换的 js,无需在页面进行 less 的编译,提升了切换速度。

方案四

  • 原理:发布线上之前就将 CSS 解析好,线上的时候只需要解析这些已经处理好的样式文件即可。灵感源于方案三。

  • 开源实现:webpack-stylesheet-variable-replacer-plugin github.com/eaTong/webp…

  • 评论:支持 key–value 方式来定义需要替换的变量,还有就是注入文件可控,不会重复注入,方便使用。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享