写在开头

时隔大半个月,最近终于又有些时间来写文章啦( ̄▽ ̄),写文章我一直认为是一种巩固知识的好方式,不仅加深、巩固自己学到的东西,而且会有一个比较好的整理归纳,也能方便自己随时的查阅。

而这次分享的文章主题是 element-ui 源码系列,element-ui 包括新版的 element-plus 我一直认为是两个非常棒的 UI 框架(当然其他框架也很棒啦,手动狗头保命-.-),它们是值得我们去细细品读的,你会学到很多东西,真的,信我,不吃亏。

准备

那我们废话不多说,赶紧来开始!

创建入口文件

首先,在你的电脑里寻找一个风水宝地,创建一个文件夹,通过 npm init -y,初始化 package.json 文件;创建 src 文件夹,在它下面创建 src/index.js 入口文件,它是我们项目的总入口文件。

修改element源码样式 elementui源码_Vue

创建第一个组件

其次,我们来创建项目的第一个组件,先在 src 文件夹 同级 下创建 packages 文件夹,它后续会存放我们项目中的每一个组件源码;再创建第一个组件 button 的结构目录,具体如下:

修改element源码样式 elementui源码_javascript_02

后续每个组件都会在 package 文件夹下有对应名称的文件夹,它主要由一个 index.js 主文件,和 src 文件夹组成,这和 element-ui 源码结构是一样的,都是基操,就不多说了,看着建就完事。

编写入口文件与组件内容

入口文件(src/index.js)的工作就是引入注册所有组件,并对外提供 install() 方法,供给 Vue.use() 方法使用。

// src/index.js
import Button from '../packages/Button/index.js';

const components = [Button];

const install = (Vue) => {
  components.forEach(component => {
    Vue.component(component.name, component); // 每个组件需提供 name 属性
  })
}

export default {
  install,
  Button
}

button.vue 组件我们先简单随便写点东西。

// button.vue
<template>
  <div>第一个组件-button组件</div>
</template>

<script>
export default {
  name: 'ElButton'
};
</script>

button/index.js 组件名称我们先按 element-ui 本身的名称来,当然,你也能随便改,这不是重点。

// button/index.js
import ElButton from './src/button.vue'; // 后缀不可省略

/* istanbul ignore next */
ElButton.install = function(Vue) { // 提供给按需加载能力
  Vue.component(ElButton.name, ElButton);
};

export default ElButton;

在编写 button/index.js 文件的时候,有两个需要注意的地方:一就是文件后缀的问题,因为我们项目是从零开始搭建的,没有任何其他辅助工具,所以在引入一个文件的时候,必须提供一个完整的路径。很多时候,我们已经习惯了引入文件时,省略 .js.vue.ts 等后缀,但这不是一个与生俱来的“能力”,那是因为我们有各种 cli 工具的集成辅助,当然,后面我们集成 webpack 后也能配置该能力;第二个需要注意的地方是在组件身上挂载 install() 方法,它的作用提供组件的 按需加载 能力,后续文章会写到,可以先不管。

打包

通过上面步骤,项目的准备工作就做完了,下面需要对项目进行打包操作,我们和 ElementUI 一样采用 webpack 来打包。

引入webpack

我们会用到两个 webpack 相关的包,为了保证不会出现不必要的麻烦,你可以先和我保持一样的版本:npm install webpack@4.14.0 webpack-cli@3.0.8 -D

之后在项目根目录下,新建 build 文件夹,它存放项目打包的一切相关配置文件,再创建 build/webpack.common.js 配置文件。

修改element源码样式 elementui源码_javascript_03

编写 webpack 的基本配置:

// build/webpack.common.js
const path = require('path');

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  output: {
    path: path.resolve(process.cwd(), './lib'),
    filename: 'element-ui.common.js',
    libraryTarget: 'commonjs2', // 将库的返回值分配给module.exports
  }
};

处理 .vue文件

因为我们编写的组件用的是 .vue 后缀的文件, webpack 可不认识这类型的文件,webpack 只识别 .js.json 文件,其他所有类型的文件,都需要找到相关的 loader 处理后才能交给 webpack

loaderwebpack 的核心内容,这里就不多讲了,不懂的可以先找些文章瞅瞅)

处理 .vue 文件我们主要会用到两个包: npm install vue-loader@15.7.0 vue-template-compiler@2.6.14 -D

编写配置文件:

// build/webpack.common.js
const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin');

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  output: {
    path: path.resolve(process.cwd(), './lib'),
    filename: 'element-ui.common.js',
    libraryTarget: 'commonjs2', // 将库的返回值分配给module.exports
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: {
          compilerOptions: {
            preserveWhitespace: false // 打包后清除多余的空格
          }
        }
      },
    ]
  },
  plugins: [
    new VueLoaderPlugin()
  ]
};

配置命令行打包

写好配置文件后,我们再配置打包命令,方便后续的打包工作。

{
  "name": "juejin-element-ui",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "webpack --config build/webpack.common.js"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "vue-template-compiler": "^2.6.14",
    "vue-loader": "^15.7.0",
    "webpack": "^4.14.0",
    "webpack-cli": "^3.0.8"
  },
  "dependencies": {}
}

执行打包命令

配置完打包命令后,我们执行它(npm run build),在项目的根目录下的 lib 文件夹应该可以生成一个 element-ui.common.js 文件。

修改element源码样式 elementui源码_elementui_04

如果执行打包有报错,不要慌,仔细报错信息,webpack 打包错误提示还是很友好的,或者你可以截图给我留言。

测试

做到这里到这里,项目前期的工作就做完了,下面我们步入测试阶段,写了那么多,是骡子是马要拉到页面上遛遛。

下面会介绍两种测试项目的方式:

方式一:项目打包成本地npm包

  • 修改 package.json 文件的 main 配置项,改成打包后生成的文件。
{
  "name": "juejin-element-ui",
  "version": "1.0.0",
  "description": "",
  "main": "lib/element-ui.common.js",
  "scripts": {
    "build": "webpack --config build/webpack.common.js"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "vue-template-compiler": "^2.6.14",
    "vue-loader": "^15.7.0",
    "webpack": "^4.14.0",
    "webpack-cli": "^3.0.8"
  },
  "dependencies": {}
}
  • 执行 npm pack 命令,生成 .tgz 包。

修改element源码样式 elementui源码_vue.js_05

  • 下载本地的 npm 包到实际项目中使用。
    我们先随便初始化一个 Vue 项目。
vue create juejin-element-ui-test(项目名,可以随意取)

然后我们在新项目中下载我们刚刚生成的本地 npm 包。

npm install F:\juejin-element-ui\juejin-element-ui-1.0.0.tgz(本地放置tgz包的全路径)

下完后,你的 Vue 项目的 package.json 文件会多一个包,之后就能和正常下载的 npm 包一样使用了。

修改element源码样式 elementui源码_修改element源码样式_06

在项目的 main.js 文件中全局导入。

import juejinElementUI from 'juejin-element-ui';
Vue.use(juejinElementUI);

在页面中具体使用。

<template>
  <div id="app">
    <el-button></el-button>
  </div>
</template>

<script>
export default {
  name: 'App',
}
</script>

修改element源码样式 elementui源码_Vue_07

能看到组件被正常识别,就大功告成了。这过程还是比较容易出错,多注意是否有重新打包、重新下载、重新启动项目等。٩(๑❛ᴗ❛๑)۶

简单总结:

1.记得把原项目打包 npm run build
2.修改 package.json 文件的 main 配置项,定位到打包后生成的入口文件。
3.执行 npm pack 打包生成 tgz 包。
4.下载 npm install 本地放置tgz包的全路径

方式二:html文件快速测试.vue文件

  • 创建一个 .html 文件。
    我们在项目中创建 examples 文件夹,在它下面创建一个 .html 文件。

修改element源码样式 elementui源码_修改element源码样式_08

  • 编写 html 文件内容。
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Vue组件库测试</title>
  <script src="https://unpkg.com/vue"></script>
  <script src="https://unpkg.com/http-vue-loader"></script>
</head>
<body>
  <div id="app">
    <el-button></el-button>
  </div>
  <script type="text/javascript">
    var app = new Vue({
      el: '#app',
      data: {},
      components: {
        'ElButton': httpVueLoader('../packages/button/src/button.vue')
      }
    })
  </script>
</body>
</html>

主要是借用 http-vue-loader 包来处理 .vue 文件,对它不熟悉的小伙伴可以自行了解一下。

  • .vue 文件 export default 改成 module.exports = {} 形式。
<template>
  <div>第一个组件-button组件</div>
</template>

<script>
// export default {
module.exports = {
  name: 'ElButton'
};
</script>

<style scoped>
</style>
  • 运行 .html 文件,必须以在服务器形式运行。
    我们需要启动一个服务器,通过服务器的形式来访问我们创建的 index.html,http-vue-loader 提供的例子借助 express 来启动,这里我们简单点,直接用 webpack-dev-server 包: npm install webpack-dev-server@3.1.11 -D

再来配置一条启动服务器的命令:

{
  "name": "juejin-element-ui",
  "version": "1.0.0",
  "description": "",
  "main": "lib/element-ui.common.js",
  "scripts": {
    "dev": "webpack-dev-server --config build/webpack.common.js",
    "build": "webpack --config build/webpack.common.js"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "vue-loader": "^15.7.0",
    "vue-template-compiler": "^2.6.14",
    "webpack": "^4.14.0",
    "webpack-cli": "^3.0.8",
    "webpack-dev-server": "^3.1.11"
  },
  "dependencies": {}
}

执行 npm run dev ,访问 http://localhost:8081/examples/ 就能看到效果啦。

修改element源码样式 elementui源码_elementui_09

有个坑: 在我们做完上述步骤后,我们要运行 .html 文件,这里可不要直接就双击去打开它,要不你只能收到一系列的报错。

修改element源码样式 elementui源码_修改element源码样式_10

主要是 http-vue-loader 的使用需要一些环境要求:

修改element源码样式 elementui源码_javascript_11




至此,本篇文章就写完啦,撒花撒花。