如何快速为团队打造自己的组件库(下)—— 基于 element-ui 为团队打造自己的组件库

当学习成为了习惯,知识也就变成了常识。感谢各位的 点赞收藏评论

新视频和文章会第一时间在微信公众号发送,欢迎关注:李永宁lyn

文章已收录到 github,欢迎 Watch 和 Star。

简介

在了解 Element 源码架构 的基础上,接下来我们基于 element-ui 为团队打造自己的组件库。

主题配置

基础组件库在 UI 结构上差异很小,一般只是在主题色上会有较大差异,毕竟每个团队都有了 UI 风格。比如,我们团队的 UI 设计稿其实是基于 Ant Design 来出的,而组件库是基于 Element-UI 来开发,即使是这种情况,对组件本身的改动也很少。所以,基于开源库打造团队自己的组件库时,主题配置就很重要了。

element-ui 的一大特色就是支持自定义主题,它通过在线主题编辑器、Chrome 插件或命令行主题工具这三种方式来定制 element-ui 所有组件的样式。那么 element-ui 是怎么做到这一点的呢?

因为 element-ui 组件样式中的颜色、字体、线条等样式都是通过变量的方式引入的,在 packages/theme-chalk/src/common/var.scss 中可以看到这些变量的定义,这就为自定义主题提供了方便,因为我们只需要修改这些变量,就可以实现组件主题的改变。

在线主题编辑器和 Chrome 插件支持实时预览。并且可以下载定制的样式包,然后使用。在线主题编辑器和 Chrome 插件的优点是可视化,简洁明了,但是有个最大的缺点就是,最后下载出来的是一个将所有组件样式打包到一起的样式包,没办法支持按需加载,不推荐使用。这里我们使用命令行主题工具来定制样式。

命令行主题工具

  • 初始化项目目录并安装主题生成工具(element-theme)

    mkdir theme && cd theme && npm init -y && npm i element-theme -D
    
  • 安装白垩主题

    npm i element-theme-chalk -D
    
  • 初始化变量文件

    node_modules/.bin/et -i
    

    命令执行以后可能会得到如下报错信息

    如何快速为团队打造自己的组件库(下)—— 基于 element-ui 为团队打造自己的组件库_第1张图片

    原因是 element-theme 包中依赖了低版本的 graceful-fs,低版本 graceful-fs 在高版本的 node.js 中不兼容,最简单的方案是升级 graceful-fs。

    在项目根目录下创建 npm-shrinkwrap.json 文件,并添加如下内容:

    {
         
       "dependencies": {
         
           "graceful-fs": {
         
               "version": "4.2.2"
           }
       }
    }
    

    运行 npm install 重新安装依赖即可解决,然后重新执行 node_modules/.bin/et -i,执行完以后会在当前目录生成 element-variables.scss 文件。

  • 修改变量

    直接编辑 element-variables.scss 文件,例如修改主题色为红色,将文件中的 $--color-primary 的值修改为 red$--color-primary: red !default;

    文件中写了很好的注释,并且样式代码也是按照组件来分割组织的,所以大家可以对照设计团队给到的设计稿来一一修改相关的变量。如果实在觉得看代码比较懵,可以参照在线主题编辑器,两边的变量名是一致的。

    题外话:element-ui 还提供了两个资源包,供设计团队使用,所以最理想的是,让设计团队根据 element-ui 的资源包出设计稿,这样两边就可以做到统一,研发团队的工作量也会降低不少。比如我们团队就不是这样,设计团队给到的设计稿是基于 Ant Design 出的,研发组件库时改动的工作量和难度就会相对比较大。所以研发、设计、产品一定要进行很好的沟通。

  • 编译主题

    修改完以后,保存文件,然后执行以下命令编译主题,会产生一个 theme 目录。生产出来都是 CSS 样式文件,文件名和组件名一一对应,支持按需引入(指定组件的样式文件)和全量引入(index.css)。

    • 生产未压缩的样式文件

      node_modules/.bin/et --out theme-chalk
      
    • 生产经过压缩的样式文件

      node_modules/.bin/et --minimize --out theme-chalk
      
    • 帮助命令

      node_modules/.bin/et --help
      
    • 启用 watch 模式,实时编译主题

      node_modules/.bin/et --watch --out theme-chalk
      
  • 使用自定义主题

    • 用新生成的主题目录(theme-chalk)替换掉框架中的 packages/theme-chalk 目录。重命名老的 theme-chalk 为 theme-chalk.bak,不要删掉,后面需要用

      建议将生成主题时用到的 element-variables.scss 文件保存在项目中,因为以后你可能会需要重新生成主题

    • 修改 /examples/entry.js/examples/play.js/examples/extension/src/app.js 中引入的组件库的样式

      // 用新的样式替换旧的默认样式
      // import 'packages/theme-chalk/src/index.scss
      import 'packages/theme-chalk/index.css
      
    • 修改 /build/bin/iconInit.js 中引入的图标样式文件

      // var fontFile = fs.readFileSync(path.resolve(__dirname, '../../packages/theme-chalk/src/icon.scss'), 'utf8');
      var fontFile = fs.readFileSync(path.resolve(__dirname, '../../packages/theme-chalk/icon.css'), 'utf8');
      
    • 修改 /examples/docs/{四种语言}/custom-theme.md

      // @import "~element-ui/packages/theme-chalk/src/index";
      @import "~element-ui/packages/theme-chalk/index";
      
    • 执行 make dev 启动开发环境,查看效果

      如何快速为团队打造自己的组件库(下)—— 基于 element-ui 为团队打造自己的组件库_第2张图片

    到这一步,主题配置就结束了,你会发现,element-ui 官网的组件样式基本上和设计稿上的一致。但是仔细对比后,会发现有一些组件的样式和设计稿有差异,这时候就需要对这些组件的样式进行深度定制,覆写不一致的样式。

    其实这块儿漏掉了 /build/bin/new.js 中涉及的样式目录,这块儿的改动会放到后面

样式深度定制

上一步的主题配置,只能解决主题相关的样式,但是有些组件的有些样式不属于主题样式,如果这部分样式刚好又和设计稿不一致的话,那就需要重写这部分样式去覆盖上一步的样式。

以下配置还支持为自定义组件添加样式

样式目录

  • 主题配置 步骤中备份的 /packages/theme-chalk.bak 重命名为 /packages/theme-lyn,作为覆写组件和自定义组件的样式目录

  • 删掉 /packages/theme-lyn/src 目录的所有文件

  • 你会写 scss ?

    • 忽略掉下一步,然后后续步骤你只需将对应的 less 操作换成 sass 即可
  • 你不会写 scss,扩展其它语法,假设你会写 less

    • 在项目根目录执行以下命令,然后删掉 gulp-sass

      npm i less less-loader gulp-less -D && npm uninstall gulp-sass -D
      

      如果一会儿启动开发环境以后,报错 “TypeError: this.getOptions is not a function”,则降级 less-loader 版本,比如我的版本是:[email protected][email protected]

    • /packages/theme-lyn 目录下执行以下命令,然后删掉 gulp-sass

      npm i gulp-less -D && npm uninstall gulp-sass -D
      
    • /packages/theme-lyn/gulpfile.js 更改为以下内容

      'use strict';
      
      /**
       *  将 ./src/*.less 文件编译成 css 文件输出到 ./lib 目录
       *  将 ./src/fonts/中的所有字体文件输出到 ./lib/fonts 中,如果你没有覆写字体样式的需要,则删掉拷贝字体样式部分
       */
      const {
              series, src, dest } = require('gulp');
      const less = require('gulp-less');
      const autoprefixer = require('gulp-autoprefixer');
      const cssmin = require('gulp-cssmin');
      const path = require('path')
      
      function compile() {
             
        return src('./src/*.less')
          .pipe(less({
             
            paths: [ path.join(__dirname, './src') ]
          }))
          .pipe(autoprefixer({
             
            browsers: ['ie > 9', 'last 2 versions'],
            cascade: false
          }))
          .pipe(cssmin())
          .pipe(dest('./lib'));
      }
      
      function copyfont() {
             
        return src('./src/fonts/**')
          .pipe(cssmin())
          .pipe(dest('./lib/fonts'));
      }
      
      // 也可以在这里扩展其它功能,比如拷贝静态资源
      
      exports.build = series(compile, copyfont);
      
      
    • build/webpack.demo.js 中增加解析 less 文件的规则

      {
             
        test: /\.less$/,
        use: [
          isProd ? MiniCssExtractPlugin.loader : 'style-loader',
          'css-loader',
          'less-loader'
        ]
      }
      
  • 假如你要覆写 button 组件的部分样式

    • /packages/theme-lyn/src 目录下新建 button.less 文件,编写覆写样式时请遵循如下规则

      • 组件样式的覆写,最好遵循 BEM 风格,目的是提供良好的命名空间隔离,避免样式打包以后发生意料之外的覆盖
      • 只覆写已有的样式,可以在组件上新增类名,但不要删除,目的是兼容线上代码
      // 这里我要把主要按钮的字号改大有些,只是为了演示效果
      .el-button--primary {
        font-size: 24px;
      }
      
  • 改造 build/bin/gen-cssfile.js 脚本

    /**
     * 将各个覆写的样式文件在 packages/theme-lyn/src/index.less 文件中自动引入
     */
    
    var fs = require('fs');
    var path = require('path');
    
    // 生成 theme-lyn/src 中的 index.less 文件
    function genIndexLessFile(dir) {
         
      // 文件列表
      const files = fs.readdirSync(dir);
      /**
       * @import 'x1.less';
       * @import 'x2.less;
       */
      let importStr = "/* Automatically generated by './build/bin/gen-cssfile.js' */\n";
    
      

你可能感兴趣的:(组件库,前端,javascript,组件化,elementui,vue.js)