likes
comments
collection
share

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

作者站长头像
站长
· 阅读数 5

如果你在国内使用 Vue 2 开发站点网页,特别是后台管理之类的界面。那你肯定接触过 Element UI,这是由饿了么前端团队对外开源的一套 UI 库,国内使用非常广泛。

饿了么前端团队并没有针对 Element UI 进行 Vue 3 版本的升级,这部分工作由社区在开发和维护,为了与 Element UI 做区分,改叫 Element Plus 了。

虽然 Vue 3 发布已经有一段时间了,而且 Vue 2 也已经于 2023 年 12 月 31 号结束了官方更新支持。不过鉴于国内仍有大量使用 Vue 2 的项目在运行中,学习 Element UI 就显得比较有现实意义了——不管是代码维护,还是后续升级,了解 Element UI 的基本概况和源码架构都是必要的。

我们将从基本概况开始讲。

基本概况

安装

Element UI 支持以 npm 包或 CDN 方式安装使用。

一、CDN 方式

<!-- 引入样式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- 引入 Vue 2 -->
<script src="https://unpkg.com/vue@2"></script>
<!-- 引入组件库 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>

二、npm 包方式

安装 element-ui 依赖。

$ npm install element-ui 

在项目的 main.js 文件中引入 Element UI。

import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import App from './App.vue';

Vue.use(ElementUI);

new Vue({
  el: '#app',
  render: h => h(App)
});

以上我们就完成了 Element UI 的全局引入。如果需要按需引入,可以通过在 .babelrc 中接入 babel-plugin-component 实现。

国际化

Element UI 默认语言环境是中文,如果需要改成其他语言(比如:英文),可以在引入 Element UI 时,指定 locale 属性实现。

// 完整引入 Element
import Vue from 'vue'
import ElementUI from 'element-ui'
import locale from 'element-ui/lib/locale/lang/en'

Vue.use(ElementUI, { locale })

或是借助 Element UI 对外暴露出来的 locale 作用域对象上的 .use() 方法。

// 按需引入 Element
import Vue from 'vue'
import { Button, Select } from 'element-ui'
import lang from 'element-ui/lib/locale/lang/en'
import locale from 'element-ui/lib/locale'

// 设置语言
locale.use(lang)

// 引入组件
Vue.component(Button.name, Button)
Vue.component(Select.name, Select)

接下来,就来介绍 Element UI 提供的一些重要组件能力。

我们可以将这些组件按照功能点进行分类,包括:基础组件、表单组件、数据展示组件、导航类组件、反馈组件。下面分别它们进行概括性的介绍。

基础组件

这里主要包含在构建页面时常用的元素:布局、按钮、图标以及文字展示。

布局组件

布局组件有两种:一种是容器组件 <el-container>/<el-header>/<el-main>/<el-footer>/<el-aside>,还有一种是由 24 分栏构成的布局组件 <el-row><el-col>

容器组件 <el-container>

<template>
  <el-container>
    <el-header>Header</el-header>
    <el-container>
      <el-aside width="200px">Aside</el-aside>
      <el-container>
        <el-main>Main</el-main>
        <el-footer>Footer</el-footer>
      </el-container>
    </el-container>
  </el-container>
</template>

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

分栏组件 <el-row><el-col>

<el-row :gutter="20">
  <el-col :span="16"><div class="grid-content bg-purple"></div></el-col>
  <el-col :span="8"><div class="grid-content bg-purple"></div></el-col>
</el-row>
<el-row :gutter="20">
  <el-col :span="12"><div class="grid-content bg-purple"></div></el-col>
  <el-col :span="12"><div class="grid-content bg-purple"></div></el-col>
</el-row>

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

<!-- 启用 Flex 布局 -->
<el-row type="flex" class="row-bg" justify="space-between">
  <el-col :span="6"><div class="grid-content bg-purple"></div></el-col>
  <el-col :span="6"><div class="grid-content bg-purple-light"></div></el-col>
  <el-col :span="6"><div class="grid-content bg-purple"></div></el-col>
</el-row>

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

按钮组件

按钮是网页中非常常用的元素了,使用 <el-button> 表示。

<el-button>默认按钮</el-button>
<el-button type="primary">主要按钮</el-button>
<el-button type="success">成功按钮</el-button>
<el-button type="info">信息按钮</el-button>
<el-button type="warning">警告按钮</el-button>
<el-button type="danger">危险按钮</el-button>

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

图标组件

Element UI 内置一套图标集合。你可以通过设置 el-icon-[icon-name] 类名的方式启用。

<i class="el-icon-edit"></i>
<i class="el-icon-delete"></i>

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

当然,某些组件(比如:按钮组件)还通过 icon prop 内置了图标支持。

<el-button type="primary" icon="el-icon-search">搜索</el-button>

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

文字链接

这类组件通常用作跳转链接或是执行某些特定操作。

<!-- 链接跳转 -->
<el-link href="https://element.eleme.io" target="_blank">默认链接</el-link>
<!-- 执行特定操作 -->
<el-link icon="el-icon-edit">编辑</el-link>
<el-link>查看<i class="el-icon-view el-icon--right"></i> </el-link>

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

表单组件

这类组件很多,我们这里只挑一些常用地说。包括:<el-form> & <el-form-item><el-input><el-select> & <el-option><el-date-picker><el-checkbox-group> & <el-checkbox><el-radio-group> & <el-radio><el-switch>

表单容器组件

按照约定,所以表单组件都应该写在 <el-form> 中,它的作用类似 HTML 中的 <form> 标签,不过做了一些功能增强。同时,每个表单组件还要包装在 <el-form-item> 中,它的作用类似 HTMl 的 <label> 标签,不过做了一些功能增强。

<el-form ref="form" :model="form" label-width="80px">
  <el-form-item label="活动名称">
    <el-input v-model="form.name"></el-input>
  </el-form-item>
  <el-form-item label="活动形式">
    <el-input type="textarea" v-model="form.desc"></el-input>
  </el-form-item>
</el-form>

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

常用表单组件

包含输入框 <el-input>、选择框 <el-select>、开关按钮 <el-switch>、日期选择 <el-date-picker>

<el-form ref="form" :model="form" label-width="80px">
  <el-form-item label="活动名称">
    <el-input v-model="form.name"></el-input>
  </el-form-item>
  <el-form-item label="活动区域">
    <el-select v-model="form.region" placeholder="请选择活动区域">
      <el-option label="区域一" value="shanghai"></el-option>
      <el-option label="区域二" value="beijing"></el-option>
    </el-select>
  </el-form-item>
  <el-form-item label="活动时间">
    <el-col :span="11">
      <el-date-picker type="date" placeholder="选择日期" v-model="form.date" style="width: 100%;"></el-date-picker>
    </el-col>
  </el-form-item>
  <el-form-item label="即时配送">
    <el-switch v-model="form.delivery"></el-switch>
  </el-form-item>
</el-form>

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

单选、多选元素

Element UI 中,<el-radio><el-checkbox> 用来表示单选、多选元素。这些元素通常成组出现,因此会放在对应的包装组件中(<*-group> )。

<el-form ref="form" :model="form" label-width="80px">
  <el-form-item label="活动性质">
    <el-checkbox-group v-model="form.type">
      <el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox>
      <el-checkbox label="地推活动" name="type"></el-checkbox>
      <el-checkbox label="线下主题活动" name="type"></el-checkbox>
      <el-checkbox label="单纯品牌曝光" name="type"></el-checkbox>
    </el-checkbox-group>
  </el-form-item>
  <el-form-item label="特殊资源">
    <el-radio-group v-model="form.resource">
      <el-radio label="线上品牌商赞助"></el-radio>
      <el-radio label="线下场地免费"></el-radio>
    </el-radio-group>
  </el-form-item>
</el-form>

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

数据展示组件

顾名思义,这类组件通常跟数据展示相关。

状态占位元素

这类组件有 3 种。一种是骨架屏组件 <el-skeleton>,一种是空状态组件 <el-empty>,还有一个是加载组件。

<el-skeleton :rows="6" animated />

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

<el-empty description="描述文字"></el-empty>

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

加载组件比较特殊,你既可以通过 v-loading 指令(绑定 boolean 值)的方式创建,也可以通过调用组件实例上的 .$loading() 方法创建。

<!-- 区域加载效果 -->
<template>
  <el-table
    v-loading="loading"
    :data="tableData"
    ...
  >
  ...
</template>
<template>
  <el-button
    type="primary"
    @click="openFullScreen">
    服务方式
  </el-button>
</template>

<script>
  export default {
    data() {
      return {
        fullscreenLoading: false
      }
    },
    methods: {
      openFullScreen2() {
        const loading = this.$loading({
          lock: true,
          text: 'Loading',
          spinner: 'el-icon-loading',
          background: 'rgba(0, 0, 0, 0.7)'
        });
        setTimeout(() => {
          loading.close();
        }, 2000);
      }
    }
  }
</script>

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

v-loading 指令来说,Loading 遮罩默认会覆盖当前绑定元素上。而对以 .$loading() 方法创建的 Loading 遮罩默认整页加载效果,你可以通过设置 target 选项实现局部加载效果。

结果数据展示组件

这类组件有 4 种:一种是用于统计数据展示的统计组件 <el-statistic>,一种是用于展示列表描述数据的组件 <el-descriptions> & <el-descriptions-item>,一种是用于描述操作结果的 <el-result> 组件,最后是表格组件 <el-table>

先来看看前三个的使用:

<el-statistic
  group-separator=","
  :precision="2"
  :value="1314"
  :title="'增长人数'"
></el-statistic>

<el-descriptions title="用户信息">
    <el-descriptions-item label="用户名">kooriookami</el-descriptions-item>
    <el-descriptions-item label="手机号">18100000000</el-descriptions-item>
</el-descriptions>

<el-result icon="success" title="成功提示" subTitle="请根据提示进行操作">
  <template slot="extra">
    <el-button type="primary" size="medium">返回</el-button>
  </template>
</el-result>

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

<el-table> 的使用相对复杂一些,不过能够实现的功能也更加多样。

<template>
  <el-table
    :data="tableData"
    style="width: 100%">
  </el-table-column>
    <el-table-column
      prop="name"
      label="姓名"
      width="180">
    </el-table-column>
    <el-table-column
      prop="address"
      label="地址">
    </el-table-column>
  </el-table>
</template>
<script>
  export default {
    data() {
      return {
        tableData: [{
          date: '2016-05-02',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 弄'
        },
        {
          date: '2016-05-04',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1517 弄'
        }]
      }
    }
  }
</script>

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

修饰性小组件

这类组件包括:标记组件 <el-badge>、头像组件 <el-avatar> 以及标签组件 <el-tag>

<template>
  <el-badge :value="12" class="item">
    <el-button size="small">评论</el-button>
  </el-badge>

  <el-avatar :size="50" src="https://picsum.photos/160/160"></el-avatar>

  <el-tag>标签一</el-tag>
  <el-tag type="success">标签二</el-tag>
  <el-tag type="info">标签三</el-tag>
</template>

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

导航类组件

这类组件一共有 3 种。一种是用于网站导航菜单栏组件 <el-menu> & <el-menu-item>,一种是用于分隔页面内不同内容类型的标签页组件 <el-tabs> & <el-tab-pane>,最后还有用于展示页面路径的组件 <el-page-header>(适应于简单场景) 和 <el-breadcrumb> & <el-breadcrumb-item>(适应于复杂场景) 。

<template>
  <el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal" @select="handleSelect">
    <el-menu-item index="1">处理中心</el-menu-item>
    <el-menu-item index="2" disabled>消息中心</el-menu-item>
    <el-menu-item index="3"><a href="https://www.ele.me" target="_blank">订单管理</a></el-menu-item>
  </el-menu>

  <el-tabs v-model="activeTab" @tab-click="handleClick">
    <el-tab-pane label="用户管理" name="first">用户管理</el-tab-pane>
    <el-tab-pane label="配置管理" name="second">配置管理</el-tab-pane>
  </el-tabs>

  <!-- 简单场景 -->
  <el-page-header @back="goBack" content="详情页面"></el-page-header>
  
  <!-- 复杂场景 -->
  <el-breadcrumb separator="/">
    <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
    <el-breadcrumb-item><a href="/">活动管理</a></el-breadcrumb-item>
    <el-breadcrumb-item>活动列表</el-breadcrumb-item>
  </el-breadcrumb>
</template>

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

反馈组件

这类组件主要有 3 种。一种是弹出框类型的 MessageBox、<el-dialog><el-popconfirm>,一种是消息通知类型的 Notification 和 Message,一种是文字提示类型的 <el-tooltip><el-popover>

弹出框组件

MessageBox 是美化系统自带的 alert()confirm()prompt() 的,因此适合展示较为简单的内容,稍微复杂一些的就要使用 <el-dialog> 组件。

MessageBox 是在 Element UI 全局注册后,可以通过 this.$alert()this.$confirm()this.$prompt() 访问到。

<template>
  <el-button type="text" @click="open">点击打开 Message Box</el-button>
</template>

<script>
  export default {
    methods: {
      open() {
        this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          // confirm
        }).catch(() => {
          // cancel       
        });
      }
    }
  }
</script>

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

<el-dialog> 组件上则能实现内容丰富、结构灵活的内容展示。

<el-button type="text" @click="dialogVisible = true">点击打开 Dialog</el-button>

<el-dialog
  title="提示"
  :visible.sync="dialogVisible"
  width="30%"
  :before-close="handleClose">
  <span>这是一段信息</span>
  <span slot="footer" class="dialog-footer">
    <el-button @click="dialogVisible = false">取 消</el-button>
    <el-button type="primary" @click="dialogVisible = false">确 定</el-button>
  </span>
</el-dialog>

<script>
  export default {
    data() {
      return {
        dialogVisible: false
      };
    },
    methods: {
      handleClose(done) {
        this.$confirm('确认关闭?')
          .then(_ => {
            done();
          })
          .catch(_ => {});
      }
    }
  };
</script>

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

<el-popconfirm> 则是带有跟随功能的小型确认框组件,俗称“气泡确认框”。通常用于行内局部展示的确认操作。

<template>
<el-popconfirm
  title="这是一段内容确定删除吗?"
>
  <el-button slot="reference">删除</el-button>
</el-popconfirm>
</template>

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

消息通知组件

一共包含 2 种:Notification 和 Message。Element UI 在全局注册后,会以组件实例上方法的形式提供。

Notification 通过 this.$notify() 调用,展示侧边栏消息提示。

<template>
  <el-button
    plain
    @click="open">
    可自动关闭
  </el-button>
</template>

<script>
  export default {
    methods: {
      open() {
        const h = this.$createElement;

        this.$notify({
          title: '标题名称',
          message: h('i', { style: 'color: teal'}, '这是提示文案')
        });
      }
    }
  }
</script>

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

Message 则通过 this.$message() 调用出现,展示页面顶部消息提示。

<template>
  <el-button :plain="true" @click="open">打开消息提示</el-button>
  <el-button :plain="true" @click="openVn">VNode</el-button>
</template>

<script>
  export default {
    methods: {
      open() {
        this.$message('这是一条消息提示');
      },

      openVn() {
        const h = this.$createElement;
        this.$message({
          message: h('p', null, [
            h('span', null, '内容可以是 '),
            h('i', { style: 'color: teal' }, 'VNode')
          ])
        });
      }
    }
  }
</script>

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

文字提示组件

这类提示一般是作为页面内容的补充信息提供的。目前有 2 种:<el-tooltip><el-popover>

<el-tooltip> 用于简单场景的文字补充提示,<el-popover> 相当于是前者的增强版,能展示更多的提示信息。

<el-tooltip class="item" effect="dark" content="Top Left 提示文字" placement="top-start">
  <el-button>上左</el-button>
</el-tooltip>

<el-popover
  placement="top-start"
  title="标题"
  width="200"
  trigger="hover"
  content="这是一段内容">
  <el-button slot="reference">hover 激活</el-button>
</el-popover>

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

以上差不过是 Element UI 中所有可用组件的一个概况性介绍。各组件的具体使用,大家可以参照官方组件文档进行学习。

讲完 Element UI 的基本概况,我们再来浅谈它的源码架构。

源码架构

由于 Element UI 源码库牵涉的知识点太多。本节我们只从使用的角度分析 Element UI 源码的组织和打包方式。学有余力的同学可以在观看本节内容后,亲自去仓库中进行学习。

注意:源码基于目前最新的 v2.15.14 进行分析。

总体来说,在阅读 Element UI 源码后,你会有这样一种感受:组件代码实现上简单,UI 库打包流程则相对繁琐。

我们先从组件代码以及组件样式上进行分析。

组件结构

Element UI 组件的源码都位于仓库的 packages 目录下。

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

文档中 <el-[component-name]> 组件对应仓库 packages 目录下的 component-name 目录。比如 <el-button> 元素,就对应 button 目录,里面包含按钮组件的实现源码。

组件目录中包含 2 部分。

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

组件入口文件 index.js,以及组件实现目录 srcsrc 中会有一个跟目录同名的 .vue 文件,对应组件实现代码。

index.js 的作用主要是给组件部署 install() 方法,以 packages/button/index.js 为例。

import ElButton from './src/button';

/* istanbul ignore next */
ElButton.install = function(Vue) {
  Vue.component(ElButton.name, ElButton);
};

export default ElButton;

如此一来,我们的组件除了 Vue.component() 手动注册的方式,还能支持 Vue.use() 自动注册的方式。

import Vue from 'vue';
import { Button, Select } from 'element-ui';

Vue.component(Button.name, Button);
// 或者
Vue.use(Button)

相比较来说,Vue.use(Button) 的部署方式更加简洁。

下面,我们点开 button.vue 文件内容查看。

<template>
  <button
    class="el-button"
    @click="handleClick"
    ...
  >
    <span v-if="$slots.default"><slot></slot></span>
  <button>
<template>
<script>
  export default {
    name: 'ElButton',
    inject: {
      elForm: {
        default: ''
      },
      ...
    },
    props: {
      type: {
        type: String,
        default: 'default'
      },
      size: String,
      icon: {
        type: String,
        default: ''
      },
      ...
    },
    computed: {
      ...
      buttonDisabled() {
        return this.$options.propsData.hasOwnProperty('disabled') ? this.disabled : (this.elForm || {}).disabled;
      }
    },
    methods: {
      handleClick(evt) {
        this.$emit('click', evt);
      }
    }
</script>

你会发现 button.vue 中只包含 <template><script> 标签,并没有 <style> 标签——这是因为 Element UI 的组件样式是单独打包的。

样式打包

Element UI 的样式文件位于 packages/theme-chalk 目录下。theme-chalk 是 Element UI 的默认主题,样式文件位于 src 目录下,采用 SCSS 语法编写。

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

theme-chalk 中存储了一个个跟组件名对应的 .scss 文件。比如 <el-button> 对应的 scss 文件是 button.scss

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

当然,还有一个特殊的 index.scss 文件,包含所有组件样式。接入 Element UI 时,我们引入的样式文件就是由它构建出来的。

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

Element UI 的样式是在单独的打包流程中的,对应 package.json 文件中的 "build:theme" 命令

{
  "scripts": {
    "build:theme": "node build/bin/gen-cssfile && gulp build --gulpfile packages/theme-chalk/gulpfile.js && cp-cli packages/theme-chalk/lib lib/theme-chalk",
  }
}
  • node build/bin/gen-cssfile:确保 packages 目录下每个组件在 packages/theme-chalk/src 目录中都有对应的 .scss 文件
  • gulp build --gulpfile packages/theme-chalk/gulpfile.js:核心样式打包指令。Element UI 的样式使用 gulp 以管道任务的形式打包,gulpfile.js 文件做两件事
    • .scss 文件处理成 .css 文件,并进行文件压缩,输出到 ./lib 目录(即 packages/theme-chalk/lib
    • theme-chalk/fonts 目录下的两个字体文件(icon.scss 中引用),输出到 ./lib/fonts 目录
  • cp-cli packages/theme-chalk/lib lib/theme-chalk:表示将 packages/theme-chalk/lib 目录下编译出来的样式文件,复制到仓库根目录的 lib/theme-chalk 目录下

以上,就完成了所有组件样式文件的打包工作。

组件打包

Element UI 组件的打包采用 webpack,在执行 npm run dist 指令时执行打包。我们来看一下 dist 指令。

{
  "scripts": {
    "dist": "npm run clean && npm run build:file && npm run lint && webpack --config build/webpack.conf.js && webpack --config build/webpack.common.js && webpack --config build/webpack.component.js && npm run build:utils && npm run build:umd && npm run build:theme",
  }
}

非常长。不过,我们只需要关注 webpack --config 对应的 3 个指令即可。

说明:webpack 之前的指令主要在做代码清理、Linter 工作以及确保打包能够顺利进行的安全工作;而 webpack 之后的指令,主要在做 Element UI 周边的一些琐碎工作,包括:工具类打包、多语言文件打包(Locale)以及前一节说得主题样式打包。

先来看看 webpack --config build/webpack.conf.js命令。

umd 格式打包

webpack --config build/webpack.conf.js 的作用是将 src/index.js 文件打包成 umd 格式,然后输出到 lib/index.js 文件。

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

src/index.js 文件作用类似 index.scss 文件,汇总了所有组件的入口文件,并做了一些必要的 Element UI 库的初始化工作。

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

这一步打包出来的文件,是为了能在浏览器中直接使用的,也就是我们熟知的 CDN 引入方式

<!-- 引入样式(对应 npm run build:theme 指令的产物) -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- 引入组件库(对应 webpack --config build/webpack.conf.js 命令的产物) -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>

再来看看 webpack --config build/webpack.common.js

CommonJS 格式打包

webpack --config build/webpack.common.js 的作用是提供 CommonJS 入口文件。这个命令会将src/index.js 文件打包成 CommonJS 格式,然后输出成 lib/element-ui.common.js 文件。

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

element-ui.common.js 文件要求宿主环境具备打包能力。也就说,宿主项目在打包时,也会打包 Element UI 的文件。

注意:element-ui.common.js 文件在输出时,会经过 Babel 工具转译,将文件语法降级到 IE9+ 能够兼容的程序(参见 .babelrc 配置)。因此宿主项目不需要对 Element UI 文件在做转译工作了,直接打包就行。

另外,element-ui.common.js 被设置成项目的入口文件(package.json"main" 字段)。

{
  "main": "lib/element-ui.common.js",
}

因此,当你在项目中使用 Element UI 时,实际上就是在引入这个 lib/element-ui.common.js 文件。

import ElementUI from 'element-ui';
// 等价于
import ElementUI from 'element-ui/lib/element-ui.common.js';

最后,再来看看 webpack --config build/webpack.component.js

CommonJS 格式打包(针对一个个组件)

上一步我们完成了 Element UI 入口文件的打包工作,这是一种将 Element UI 代码全部引入项目的做法。

当然了,有时候项目中并不会用到所有组件,为了考虑到尺寸原因,需要支持按需引入。webpack --config build/webpack.component.js 命令就是用来单独打包组件源码的,让你能够按需引入。

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

这里的 Components 是从维护的 component.json 文件中读取的,对应 packages 目录下的所有组件的入口文件 index.js

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

我们从所有组件的入口文件出发,分别打包。如此,我们就完成了每个组件代码的单独打包。

最终,组件代码会被输出项目根目录下的 lib 目录中,以 [component-name].js 形式存在,配合 lib/theme-chalk 目录下的 [component-name].css 文件,就能实现按需引入了。

Element UI:基于 Vue 2 的一个 UI 库,介绍它的基本概况以及源码架构

以上,我们就讲完了 Element UI 的源码架构部分。

总结

本文我们对 Element UI 这个 Vue 2 UI 库,做了一下基本概况介绍和源码架构的分析工作。

在“基本概况”中,我们按照功能点对 Element UI 所有重点组件做了分类。包括基础组件、表单组件、数据展示组件、导航类组件、反馈组件。然后进入每个分类,进行概况性的介绍。当然,具体使用时,大家可以参照官方组件文档进行学习。

在“源码架构”中,我们从使用的角度分析了 Element UI 源码的源码组织和打包方式。Element UI 对外提供了 2 中输出格式——umd 和 CommonJS,前者让你能够在浏览器中直接使用,后者则是在通过 npm 包使用的引入的版本,需要宿主环境具备打包能力。当然,Element UI 还单独对各组件进行打包了,让你能够按需引入。

好了,到这里差不多该结束了。感谢你的阅读,再见。