基于组件库换肤方案的设计于实现

2,520 阅读2分钟

常见的换肤方案:

  1. 样式覆盖,利用css优先级的原理覆盖掉原有样式的实现
  2. 生成多套css 通过编译工具与构建工具编译出多套皮肤css,通过js动态的link对应的皮肤样式
  3. css3变量 缺点: 部分浏览器兼容性

image.png 4. 利用命名空间写不同的样式 5. 动态换肤,与后端交互,把修改的参数打包打给后端,后端把新生成的样式返回给前端,写到style样式内

组件库换肤方案的实现

前沿

组件库的命名规范 BEM BEM代表块(Block),元素(Element),修饰符(Modifier)

针对于不同的项目的换肤

以alert组件为例说一下思路

  1. 将所有UI组件公共的scss抽离成一个主题基类

  2. 每一个主题都继承于基类,并编写各自的主题变量文件

  3. 每个主题利用gulp独立打包为各自的lib文件,利用cp-cli库移动并改名

  4. 根据项目引入不同的主题文件即可

代码实现过程

目录结构:theme 主题基类、theme-peiyou 主题peiyou、theme-test主题测试

image.png

基类中alert文件的代码:
@include b(alert) {
   width: 100%;
  padding: $--alert-padding;
  margin: 0;
  box-sizing: border-box;
  border-radius: $--alert-border-radius;
  position: relative;
  background-color: $--color-white;
  overflow: hidden;
  opacity: 1;
  display: flex;
  align-items: center;
  transition: opacity .2s;
}

test主题中alert文件代码,所有的文件变量都在var文件中,不同的主题修改var文件即可:
@import "mixins/mixins";
@import "common/var";
@import "../../theme/alert.scss"
使用glup将每个主题文件中所有的scss文件打包为css文件

const { series, src, dest } = require('gulp')
const sass = require('gulp-sass')
const autoprefixer = require('gulp-autoprefixer')
const cssmin = require('gulp-cssmin')

function compile() {
 return src('./src/*.scss')
    .pipe(sass.sync())
    .pipe(
 autoprefixer({
 browsers: ['ie > 9', 'last 2 versions'],
 cascade: false
      })
    )
    .pipe(cssmin())
    .pipe(dest('./lib'))
}
exports.build = series(compile)

var变量文件中的内容
$--alert-padding: 8px 16px !default;
$--alert-title-font-size: 13px !default;
$--alert-description-font-size: 12px !default;
$--alert-close-font-size: 12px !default;
$--alert-close-customed-font-size: 13px !default

打包时候并移动修改文件名字即可完成主题
 "build:test":  "gulp build --gulpfile packages/theme-test/gulpfile.js && cp-cli packages/theme-test/lib lib/theme-test",

针对于同一个项目的换肤

在基类文件中对将部分属性样式通过css3变量方式暴露给使用者
@include b(alert) {
 width: 100%;
 padding: var(--py-alert-padding,$--alert-padding);
 margin: 0;
 box-sizing: border-box;
 border-radius:var( --py-alert-border-radius, $--alert-border-radius);
 position: relative;
 background-color: $--color-white;
 overflow: hidden;
 opacity: 1;
 display: flex;
 align-items: center;
 transition: opacity .2s;
}

image.png