相关文章推荐
捣蛋的凉茶  ·  c# - How do you call ...·  1 年前    · 

通过上一篇文章 ElementUI源码系列一 - 从零搭建项目架构,项目准备、项目打包、项目测试流程 的学习,我们搭好了项目的基本框架,如下,它们每个文件夹是各司其职,分工明确的。

这一章我们来学习一下, ElementUI 中样式是如何被使用的,我们先来分析一波:

  • 观察 element-ui 源码的 package.json 文件,可以知道它样式使用的是 scss 预处理语言;
  • 在它的源码 packages/theme-chalk/src 路径下,我们还可以发现每个组件都有对应的 .scss 文件;
  • .scss 文件最终肯定是要变成 .css 文件才能被浏览器识别的,那么它又是如何转换的呢?从 package.json 文件可以知道它使用了 gulp 来做转换,在 packages/theme-chalk/src 目录下也有关于它的配置文件。(关于 gulp 可以先自行学习一下,后面会用它写一些功能)
  • (为了方便学习,你可以下载一份 element-ui 源码在本地进行对比学习,效果会更佳)

    使用scss预处理器编写组件样式

    经过上面的分析,我们先来尝试使用 .scss 来给组件添加一些样式,再逐步也将它进行转换。首先,我们先来把我们组件代码改一改,给 button 组件添加一个类名。

    // button.vue
    <template>
      <button class="el-button">我是一个普通按钮</button>
    </template>
    <script>
    export default {
      name: 'ElButton'
    </script>
    

    其次,我们也和 ElementUI 一样,在相同目录下,给 button 组件创建相同的样式文件。

    并给它写一个最简单的样式,随便先给一个背景色,能看出效果即可,后面会使用一些 scss 语法来编写样式:

    // button.scss
    .el-button {
      background-color: red;
    

    最后,我们引入处理 .scss 需要用到的包,一共会用到四个包:npm install gulp@4.0.0 gulp-autoprefixer@6.0.0 gulp-cssmin@0.2.0 gulp-sass@4.0.2 -D

    稍微介绍下四个包的作用:

  • gulp:一种自动化构建工具,和我们熟知的 webpack 很相似,但它更纯粹一些,它基于 Node 流的能力去构建任务流,某些方面上更具性能优势,我们会采取它来处理 .scss 文件。
  • gulp-autoprefixer:由它的名字大概也能猜出它的作用了,用于自动补全 CSS 前缀的插件。
  • gulp-cssmin:用于压缩 CSS
  • gulp-sass:编译 scss,转成 CSS
  • sassscss 其实就是同一种东西,我们平时都称之为 sass ,它们俩的主要区别在于语法上,sass 是缩进语法为主,完全省略花括号;scss 是一种 CSS-like 语法,就比较接近 CSS ,更加友好和可读。

    使用gulp把scss转成css、补全、压缩

    写完 button.scss 样式文件后,要让它生效的第一步工作,我们就要把它转成 .css 文件才行。下面就正式开始 scss 的转换工作,我们先在 packages/theme-chalk 路径下创建一个 gulpfile.js 文件。

    再编写 gulp 代码,代码不多,都是 gulp 插件使用的基本语法,应该不难哈。

    // gulpfile.js
    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()) // 转成CSS
        .pipe(autoprefixer({
          browsers: ['ie > 9', 'last 2 versions'],
          cascade: false
        })) // 补全
        .pipe(cssmin()) // 压缩
        .pipe(dest('./lib')); // 在当前目录下的lib文件夹输出最终文件
    exports.build = series(compile);
    

    写完配置文件,老样子,我们为这个转换操作配置一条命令,方便后期操作。

    "scripts": {
      "dev": "webpack-dev-server --config build/webpack.common.js",
      "build": "webpack --config build/webpack.common.js",
      "build:theme": "gulp build --gulpfile packages/theme-chalk/gulpfile.js"
    

    现在在我们的项目的 package.json 文件中就有三条操作命令了,要注意记得它们分别的作用哦!

    之后我们执行命令: npm run build:theme

    应该可以看到会有一个 lib 文件夹与 .css 文件的生成,这样就完成了 .scss 文件到 .css 文件的转换,并会自动补全 CSS 前缀和压缩了 CSS(补全功能,你可以尝试使用一些有兼容性的样式试试看,这里就不多说了)。

    使用cp-cli移动css文件

    生成好了 css 文件后,就完了吗?要如何使用呢?这就需要我们回头想想,我们平常是如何使用 ElementUI 的样式文件的。

    我从 官网 上截了一张图,图中可以看到样式的引入,是在 element-ui 文件夹下的,并且它引的是一个 index.css ,我们可以先找到它对应的 .scss 文件看看:

    这应该是一个总入口样式文件,它引入所有组件的样式文件。那我们不管三七二十一,也照葫芦画瓢,先来把这个总样式文件 index.scss 创建好:

    它内容也简单,我们现在只有一个组件,所以只有一行而已:

    // index.scss
    @import "./button.scss";
    

    然后你可以再次执行刚才的命令:npm run build:theme

    可以看到 index.css 就生成完了。

    根据上面官网引入的路径,接下来我们只需要把所有的样式文件都移动到根目录下的 lib 文件夹就大功告成了。

    这个操作会借用到一个包:npm install cp-cli@1.0.2 -D

    下完 cp-cli 包后,我们把 theme:build 命令改一改:

    "scripts": {
        "dev": "webpack-dev-server --config build/webpack.common.js",
        "build": "webpack --config build/webpack.common.js",
        "build:theme": "gulp build --gulpfile packages/theme-chalk/gulpfile.js && cp-cli packages/theme-chalk/lib lib/theme-chalk"
    

    然后执行命令,观看根目录 lib 文件夹,神奇的事情是不是就发生了?(≧ω≦)(好吧,其实也不是很神奇)

    测试组件的样式文件

    做了那么多事情,又来到最后一步了,测试阶段,那么如何测试我们写的样式呢?

    在上一篇文章 ElementUI源码系列一 - 从零搭建项目架构,项目准备、项目打包、项目测试流程 最后我们介绍了两种测试方式,下面我们用第一种方式 项目打包成本地npm包 来测试组件的样式。

    测试详情过程可以去看上一篇文章,就不多介绍啦,总的来说,就是敲命令:

    原本项目:
    npm run build:theme
    npm run build
    npm pack
    测试项目:
    npm install 本地放置tgz包的全路径
    npm run serve (重启项目)

    然后在 main.js 引入样式:

    import juejinElementUI from 'juejin-element-ui';
    import 'juejin-element-ui/lib/theme-chalk/index.css'; // 引入样式
    Vue.use(juejinElementUI);
    

    最后放个效果图:

    用scss编写样式美化button组件

    我们稍微来把我们丑出天际的 button 组件美化美化,顺便用用 scss 的本来语法。当然,如果你对 scss 很熟了,你也可以跳过,这不是重点内容。

    下面我们会创建如下图红框的一些文件,这是和 ElementUI 一样的目录,它的目录、文件划分还是很合理的,是值得我们参考学习的。

    我们对 button.scss 样式文件进行改造:

    // button.scss
    @import "common/var";
    @import "mixins/mixins";
    @include b(button) {
      background: $--button-default-background-color;
      color: $--button-default-font-color;
      border-color: $--button-default-border-color;
      padding: 10px 16px;
      border: 1px solid #ccc;
      border-radius: 30px;
    

    var.scss 是整个项目的主题定义:

    // var.scss
    $--color-white: #FFFFFF !default;
    $--button-default-background-color: $--color-white !default;
    $--color-text-regular: #606266 !default;
    $--button-default-font-color: $--color-text-regular !default;
    $--border-color-base: #DCDFE6 !default;
    $--button-default-border-color: $--border-color-base !default;
    

    minxins.scss 是存放一些具有相同性质的混入,比如我们下面用到的给每个类名都添加一个 el- 的操作。

    // minxins.scss
    @import "function";
    @mixin b($block) {
      $B: $namespace+'-'+$block !global;
      .#{$B} {
        @content;
    

    function.scss 文件是存放一些 scss 函数,熟悉 scss 应该就比较了解了。

    // function.scss
    @import "config";
    

    config.scss 定义了一些变量,有项目的标识 el,还有编写样式的规范 BEM ,关于 BEM 不了解的小伙伴要赶紧自行去学习一下啦。

    // config.scss
    $namespace: 'el';
    $element-separator: '__';
    $modifier-separator: '--';
    $state-prefix: 'is-';
    

    最后我们还是再放一张效果图:

  • ElementUI源码系列一 - 从零搭建项目架构,项目准备、项目打包、项目测试流程
  • ElementUI源码系列二 - 引入scss,用gulp把scss转成css并补全、压缩,用cp-cli移动目录、文件
  • ElementUI源码系列三 - 学习gen-cssfile.js文件之自动创建组件的.scss文件与生成index.scss文件内容
  • ElementUI源码系列四 - 学习new.js文件之自动创建组件目录结构与生成components.json文件内容
  • ElementUI源码系列五 - 学习build-entry.js文件之自动生成总入口文件index.js内容
  • ElementUI源码系列六 - 小结
  • ElementUI源码系列七 - 组件按需引入
  • ElementUI源码系列八 - 搭建element-ui官方文档之项目的基本框架
  • ElementUI源码系列九 - 搭建element-ui官方文档之md文件渲染到页面、demo-block组件的实现
  • 至此,本篇文章就写完啦,撒花撒花。

    希望本文对你有所帮助,如有任何疑问,期待你的留言哦。
    老样子,点赞+评论=你会了,收藏=你精通了。

    分类:
    前端
  •