基于 Element 二次封装
# 基于 Element 二次封装
# 前言
之前在网上找过的好多都是基于 vue-cli 2.x 的,而使用 vue-cli 4 的文章比较少,所以我在自己尝试的时候把几篇文章结合了一下,调出来了我想要的模式,也就是 Vue Cli 4 + element-ui + 多个二次封装组件。 最终想要的是 element-ui 这种感觉的,很多组件可以在不同项目中复用。
# 一. 初始化项目
# 1. 安装 cli
这里我们使用官方的 vue-cli 初始化一个 Vue 项目
npm install -g @vue/cli
# or
yarn global add @vue/cli
# 创建项目
vue create admin-ui
2
3
4
5
6
# 2. 安装 element-ui
# 此处安装了 element 的指定版本
npm install element-ui@2.12.0
2
这里使用官方提供的插件安装:
在插件列表搜索 element
注意:搜索插件下载的时候,Chrome 设置里的语言设置为英文,设置可参考 《Vue UI可视化窗口修改语言》 (opens new window)
在这里我选的手动导入,图中是全部导入
然后在项目中,src 目录下新建一个 plugins 文件夹,新建个 element.js 文件,如果想手动引入,就在这里添加要依赖的组件,这里是为了调试组件:
import Vue from 'vue';
import {
Button,
Dialog
} from 'element-ui';
Vue.use(Button);
Vue.use(Dialog);
2
3
4
5
6
7
8
# 二. 规划目录结构
# 1. 调整目录
我们需要一个目录存放文件,一个目录存放示例,按照以下方式对目录进行改造。
.
...
|-- examples // 原 src 目录,改成 examples 用作示例展示
|-- packages // 新增 packages 用于编写存放组件
...
.
2
3
4
5
6
# 2. 配置项目以支持新的目录结构
我们通过上一步的目录改造后,会遇到两个问题
- src 目录更名为 examples,导致项目无法运行
- 新增 packages 目录,该目录未加入 webpack 编译
注:cli3 提供一个可选的
vue.config.js
配置文件。如果这个文件存在则他会被自动加载,所有对项目和 webpack 的配置,都在这个文件中。
2.2.1 重新配置入口,修改配置中的 pages 选项
新版 Vue CLI 支持使用 vue.config.js 中的 pages 选项构建一个多页面的应用。
这里使用 pages 修改入口到 examples
/**
* @Description: vue.config
*/
module.exports = {
// 修改 src 目录为 examples 目录
pages: {
index: {
entry: 'examples.main.js',
template: 'public/index.html',
filename: 'index.html',
},
},
};
2
3
4
5
6
7
8
9
10
11
12
13
14
2.2.2 支持对 packages 目录的处理,修改配置中的 chainWebpack 选项
- packages 是我们新增的一个目录,默认是不被 webpack 处理的,所以需要添加配置对该目录的支持。
- chainWebpack 是一个函数,会接受一个基于 webpack-chain 的 ChainableConfig 实例。允许对内部的 webpack 配置进行更细粒度的修改。
/**
* @Description: vue.config
*/
module.exports = {
// 修改 src 为 examples
pages: {
index: {
entry: 'examples/main.js',
template: 'public/index.html',
filename: 'index.html',
},
},
// 扩展 webpack 配置,使 packages 加入编译
chainWebpack: (config) => {
config.module
.rule('js')
.include
.add('packages')
.end()
.use('babel')
.loader('babel-loader')
.tap((options) => {
// 修改它的选项...
return options;
});
},
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 三. 编写组件
以上我们已经配置好对新目录框架的支持,接下来我们尝试编写组件。以下我们以一个已经发布到 npm 的小插件作为示例。
# 1. 创建一个新的组件
- 在
examples
的同级下新建packages
目录,在这里添加自己封装要发布的组件。 - 在
packages
目录下,所有的单个组件都以文件夹的形式存储。所以,这里创建一个目录button/
- 在
button/
目录下创建src/
目录存储组件源码。 - 在
button/
目录下创建index.js
文件对外提供组件的引用。
修改 /packages/button/index.js
文件,注册单独的该组件,方便使用时可以单独引用:对外提供引用
/**
* @Description: 对外提供组件引用
*/
// 导入组件,组件必须声明 name
import adminButton from './src/button';
// 为组件提供 install 安装方法,供按需引入
adminButton.install = function (Vue) {
Vue.component(adminButton.name, adminButton);
};
// 默认导出组件
export default adminButton;
2
3
4
5
6
7
8
9
10
11
12
13
14
# 2. 整合所有组件
- 整合所有组件,对外导出,即一个完整的组件库。
- 修改
/packages/index.js
文件,对整个组件库进行导出
/**
* @Description: 整合所有的组件,对外导出,即一个完整的组件库
*/
// 导入组件
import adminButton from './button';
// 存储组件列表
const components = [
adminButton,
];
// 定义 install 方法,接收 Vue 作为参数。如果使用 use 注册插件,则所有的组件都将被注册
const install = function (Vue) {
// 判断是否安装
if (install.installed) return;
// 遍历注册全局组件
components.forEach((component) => {
Vue.component(component.name, component);
});
};
if (typeof window !== 'undefined' && window.Vue) {
install(window.Vue);
}
// export default暴露出来的组件只能在使用时全局引入。
export default {
// 导出的对象必须具有 install,才能被 Vue.use() 方法安装
install,
adminButton,
};
// export暴露出来可以在使用时按需引入
export {
adminButton,
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 四. 编写示例
# 1. 在示例中导入组件库
import Vue from 'vue';
import ElementUI from 'element-ui';
import App from './App.vue';
import router from './router';
import UI from '../packages/index'; // 导入组件库
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
Vue.use(UI); // 注册组件库
Vue.config.productionTip = false;
new Vue({
router,
render: (h) => h(App),
}).$mount('#app');
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 2. 在示例中使用组件库中的组件
在上一步使用 Vue.use()
全局注册后,即可在任意页面直接使用了,而不需另外引入。当然也可以按需引入
<template>
<admin-button type="primary">主要按钮</admin-button>
</template>
2
3
# 五. 发布到 npm
到此为止,我们一个完整的组件库已经开发完成了,接下来就是发布到 npm 以供后期使用。
# 1. 新增编译库命令
在库模式中,Vue 是外置的,这意味着即使在代码中引入了 Vue,打包后的文件也是不包含 Vue 的。
Vue Cli3 构建目标:库 (opens new window)
以下我们在 package.json
里的 script
中新增一条命令 npm run lib
--target
→ 构建目标,默认为应用模式。这里修改为lib
启用库模式。--dest
→ 输出目录,默认 dist。这里我们改成lib
[entry]
→ 最后一个参数为入口文件,默认为src/App.vue
。这里我们指定编译packages/
组件目录。
"scripts": {
"lib": "vue-cli-service build --target lib --name vcolorpicker --dest lib packages/index.js",
}
2
3
执行编译库明星
npm run lib
# 2. 配置 npm 发布字段
name、version、description、main、author、private、license
以下为参考设置
main
是最重要的,这里的路径要和npm run lib
构建出来的目录和文件名对应上。
{
"name": "admin-ui",
"version": "0.1.0",
"description": "基于 Vue + element-ui 的组件库封装",
"private": false,
"main": "lib/admin-ui.common.js"
}
2
3
4
5
6
7
# 3. 设置忽略发布文件
添加 .npmignore
文件,设置忽略发布文件
我们发布到 npm 中,只有编译后的 lib 目录、package.json、README.md 才是需要被发布的。所以我们需要设置忽略目录和文件。
和 .gitignore
的语法一样,具体需要提交什么文件,看各自的实际情况。
# 忽略指定文件
.*
*.md
*.yml
*.map
yarn-error.log*
vue.config.js
babel.config.js
# 忽略目录
examples/
packages/
public/
build/
node_modules/
src/
test/
core/
packages/
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 4. 登录 npm
首先需要到 npm 上注册一个账号,注册过程略。此处为发布到私服 npm
# 使用私有仓库源
nrm use sync
# 登录
npm login
# 执行发布命令
npm publish
2
3
4
5
6
7
8
# 六. 快速使用
# 1. 安装
npm install admin-ui
# 2. 如何使用
在 main.js 中写入以下内容
import Vue from 'vue';
// element 完整应用
import Element from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(Element);
// admin ui 完整应用
import AdminUi from 'admin-ui';
import 'admin-ui/lib/admin-ui.css';
// admin ui 按需引用
import { adminButton } from 'admin-ui';
Vue.use(adminButton);
Vue.component(adminButton.name, adminButton);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 七. 附赠配置例子
{
"name": "maucash",
"description": "maucash中常用组件抽取",
"version": "1.0.2",
"author": "kuangshp <kuangshp@126.com>",
// 开源协议
"license": "MIT",
// 因为组件包是公用的,所以private为false
"private": false,
// 配置main结点,如果不配置,我们在其他项目中就不用import XX from '包名'来引用了,只能以包名作为起点来指定相对的路径
"main": "dist/maucash.js",
"scripts": {
"dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
"build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
},
"dependencies": {
"axios": "^0.18.0",
"iview": "^2.14.1",
"style-loader": "^0.23.1",
"url-loader": "^1.1.2",
"vue": "^2.5.11"
},
// 指定代码所在的仓库地址
"repository": {
"type": "git",
"url": "git+git@git.wolaidai.com:maucash/maucash.git"
},
// 指定打包后,包中存在的文件夹
"files": [
"dist",
"src"
],
// 指定关键词
"keywords": [
"vue",
"maucash",
"code",
"maucash code"
],
// 项目官网的地址
"homepage": "https://github.com/kuangshp/maucash",
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
],
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.6.0",
"babel-preset-stage-3": "^6.24.1",
"cross-env": "^5.0.5",
"css-loader": "^0.28.7",
"file-loader": "^1.1.4",
"node-sass": "^4.5.3",
"sass-loader": "^6.0.6",
"vue-loader": "^13.0.5",
"vue-template-compiler": "^2.4.4",
"webpack": "^3.6.0",
"webpack-dev-server": "^2.9.1"
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63