elementUI多套主题下换肤的关键问题:按需引入时是不支持动态换肤的
网上也有相关问题的讨论# 按需引入elementui 导致动态换肤主题被默认主题替换
组件库按需引入的原理
组件库按需引入
的原理是相似的:最终只引入指定组件和对应的样式
elementUI需要借助babel-plugin-component
ant-design-vue需要借助babel-plugin-import
以babel-plugin-component
为例
按需引入elementUI的Button组件:
import { Button } from 'element-ui'
Vue.component(Button.name, Button)
编译后的文件(自动引入button.css):
import _Button from "element-ui/lib/button";
import _Button2 from "element-ui/lib/theme-chalk/button.css";
// base.css是公共的样式,如图标和淡入淡出的动画
import "element-ui/lib/theme-chalk/base.css";
Vue.component(_Button.name, _Button);
通过按需引入来减少组件库的体积大小
组件库按需引入的换肤问题
为什么说组件库按需引入时是不支持动态换肤的?
原因1:按需引入,最终只会引入指定组件的样式,如上文的button.css,但button.css文件中只有一套样式
原因2:按需引入,组件的js和css是在路由懒加载时加载的,会导致动态换肤的主题样式会被按需引入的默认组件样式给覆盖掉
瓶颈:
elementUI和ant-design-vue均提供了多种自定义主题的方式,但无论何种方式,最终生成的button.css只有一套样式
换肤方案有哪些?
分为3类
- css样式覆盖,一般通过切换
css选择器
来实现 - 引入多套主题样式,通过
link
标签动态加载不同的主题样式 - 通过css
var()
函数,定义颜色变量的方式
缺点:
- 方案一:引入的css需要包含多套样式,导致css的代码体积变大
- 方案二:通过
link
标签加载css,需要明确的知道css文件的路径,否则会引入失败 - 方案三:兼容性不太好,IE全系版本都不兼容
不兼容IE,按需引入的换肤方案
通过方案三:css var()
来实现
优点: 没有副作用,性能好,也是腾讯、蚂蚁等主流组件库的通用换肤方案
步骤:
1、创建基础颜色变量theme.css
文件
2、修改packages/theme-chalk/src/common/var.scss
文件
将该文件的中定义的scss变量,替换成var()变量
3、修改packages/theme-chalk/gulpfile.js
打包配置
根据上文按需引入elementUI的Button组件为例:
最终会引入button.css和base.css
import _Button2 from “element-ui/lib/theme-chalk/button.css”;
import “element-ui/lib/theme-chalk/base.css”;
需要将theme.css
合并到base.css
中,这样才能保证定义的颜色变量能加载到页面中
'use strict';
const {series, src, dest} = require('gulp');
const sass = require('gulp-dart-sass');
const autoprefixer = require('gulp-autoprefixer');
const cssmin = require('gulp-cssmin');
c