前端主题切换方案(react+antd)

本文作者为 360 技术中台数据平台部的前端开发工程师

原文标题:前端主题切换方案

原文地址:https://juejin.cn/post/7117911005841063944

背景

最近有个需求,要给系统做个主题切换功能,网上关于主题的方案挺多,准备做一些调研,因为项目是react+antd的一个后台系统,开始从antd官方文档中开始着手,做下整理对比,最后选一个最佳的方案用于实践。

技术选型

less.modifyVars

antd提供的一种主题切换方式,通过配置webpack的less-loader,添加modifyVars对象,官方已经内置了一些主题变量,每次构建时更换对应色值即可实现主题切换。

// webpack.config.js
module.exports = {
  rules: [{
    test: /\.less$/,
    use: [{
      loader: 'style-loader',
    }, {
      loader: 'css-loader', // translates CSS into CommonJS
    }, {
      loader: 'less-loader', // compiles Less to CSS
+     options: {
+       lessOptions: { // 如果使用less-loader@5,请移除 lessOptions 这一级直接配置选项。
+         modifyVars: {
+           'primary-color': '#1DA57A',
+           'link-color': '#1DA57A',
+           'border-radius-base': '2px',
+         },
+         javascriptEnabled: true,
+       },
+     },
    }],
    // ...other rules
  }],
  // ...other config
}

Link标签替换

插入一个新的Link标签,用新的css链接替换原来的样式,这种方案实现上没有难度,也没有兼容问题,需要新建一套完全一样的样式类名,然后替换其中的色值,缺点是工作量太大,尤其开发中的项目来说,扩展性比较差,后期更换样式类名,需要同步更改主题样式文件:

前端主题切换方案(react+antd)_第1张图片 theme2

CSS Variable

另外一个是用ConfigProvider,需要注意在[email protected] 版本起才支持,而且webpack中如果使用了 babel-plugin-import,需要将其去除。本质是通过CSS Variable(css变量)实现,将颜色赋值变量,最大的问题是——有兼容性问题,在IE浏览器中不支持。补充:antd好像对CSS Variable做了兼容处理。

前端主题切换方案(react+antd)_第2张图片项目内需要引入使用变量样式文件:

-- import 'antd/dist/antd.min.css';
++ import 'antd/dist/antd.variable.min.css';

调用部分:

import { ConfigProvider } from 'antd';
 
ConfigProvider.config({
  theme: {
    primaryColor: '#25b864',
  },
});

css-vars-ponyfill

为弥补css variable的不足,css-vars-ponyfill做了一套兼容处理,原理大概是在ie等不支持css var的浏览器中将var()中的变量值替换为对应色值,在支持css var的浏览器中不做处理。另外是操作dom,所以在node环境中无法使用。css-vars-ponyfill主要暴露了一个cssVar方法,方法入参如下:

export interface CSSVarsPonyfillOptions {
        rootElement?: Document|HTMLElement;
        shadowDOM?: boolean;
        include?: string;
        exclude?: string;
        variables?: {[key: string]: string};   // 颜色键值对
        onlyLegacy?: boolean;
        preserveStatic?: boolean;
        preserveVars?: boolean;
        silent?: boolean;
        updateDOM?: boolean;
        updateURLs?: boolean;
        watch?: null|boolean;
        onBeforeSend?(xhr: XMLHttpRequest, elm: HTMLLinkElement|HTMLStyleElement, url: string): void;
        onError?(message: string, elm: HTMLLinkElement|HTMLStyleElement, xhr: XMLHttpRequest, url: string): void;
        onWarning?(message: string): void;
        onSuccess?(cssText: string, elm: HTMLLinkElement|HTMLStyleElement, url: string): void;
        onComplete?(cssText: string, styleElms: HTMLStyleElement[], cssVariables: {[key: string]: string}, benchmark: number): void;
        onFinally?(hasChanged: boolean, hasNativeSupport: boolean, benchmark: number): void;
    }

主要的参数:variables:颜色键值对,切换主题即更换不同的variables

技术对比

less.modifyVars是静态更改主题,适合定制化主题,构建完成之后不能再变;css标签的方法工作量太大,扩展性差;css variable比较灵活,但有兼容问题,相对于css标签方法,扩展性好点;css-vars-ponyfill是css variable的优化版,解决了兼容问题,虽然会有服务端渲染的问题,如果项目是在浏览器dom环境下无伤大雅。

补充

做了一个简单的demo,分别用三种方式实现主题切换:css标签,css variable,css-vars-ponyfill。GitHub地址:react-antd-theme

前端主题切换方案(react+antd)_第3张图片 theme_link

- END -

关于奇舞团

奇舞团是 360 集团最大的大前端团队,代表集团参与 W3C 和 ECMA 会员(TC39)工作。奇舞团非常重视人才培养,有工程师、讲师、翻译官、业务接口人、团队 Leader 等多种发展方向供员工选择,并辅以提供相应的技术力、专业力、通用力、领导力等培训课程。奇舞团以开放和求贤的心态欢迎各种优秀人才关注和加入奇舞团。

前端主题切换方案(react+antd)_第4张图片

你可能感兴趣的:(java,vue,js,html,web)