Vue是2020年的8~9月份就学了,但插件组件封装一直拖到2021年2月17日才开始看,一直以来都是直接写组件,直接调组件,业务上面也没什么大问题,但为了更进一步加深对代码和整体设计的掌控感,于是开始研究插件组件封装,这次主要讲封装插件,水平在新手入门水准,内容是:需求分析、组件编写、插件封装、打包发布、安装使用五部分。

显示效果

image-20210218092537460

整理逻辑

Vue2.x

插件组件封装主要用到4个文件: plugin.vue / plugin.js / main.js / App.vue,它们分别的功能为:

  • plugin.vue 编写组件代码,即正常的Vue组件
  • plugin.js 编写插件代码,主要用于创建组件和实例化,并通过install方法注入到全局中
  • main.js 在main中使用Vue.use(plugin)的形式调用插件
  • App.vue 在改文件中使用插件

对于plugin.vue来说,和普通的组件一样,我是这样规划的:

  1. 作为一个信息提示,首先需要输入信息,用text属性接收用户输入信息
  2. 因为我的信息长度未知,所以我希望自己调整组件的宽高,又向外暴露了width / height两个属性
  3. 弹出组件在页面的位置我想自己定义,于是我又设置了五个位置值: topRight,topLeft,center,bottomLeft,bottomRight
  4. 因为要适用于不同的场景,所以定义了类型属性(type),有info、warning、success和error四个类别
  5. 弹出后,我可以选择自动关闭或者取消自动关闭,如果是自动关闭,就需要设置多少秒后关,于是暴露了autoClose, time两个属性
  6. 最后当弹出框结束后,我需要执行其他内容,于是又定义了回调函数 callback属性,下面是所有定义的属性

组件编写

plugin.vue部分代码

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
   /* 文本     text
* 位置 position
* 宽度 width
* 高度 height
* 类型 type
* 持续时间 time
* 自动关闭 autoClose
* 回调函数 callback
* */
props: {
text: {
type: String,
default: "温馨提示",
},
width: {
type: Number,
default: 200,
},
height: {
type: Number,
default: 60,
},
position: {
type: String,
default: "center",
validator: (v) =>
["topLeft", "topRight", "center", "bottomLeft", "bottomRight"].indexOf(
v
) !== -1,
},
type: {
type: String,
validator: (v) =>
["success", "error", "warning", "info"].indexOf(v) !== -1,
},
time: {
type: Number,
default: 3000,
},
autoClose: {
type: Boolean,
default: true,
},
callback: {
type: Function,
},
},

剩下的就是一些方法的实现,这里就不一一展示了。

html代码

1
2
3
4
5
6
7
8
9
10
11
12
13
<template>
<transition name="toast">
<div
:style="{ width: `${width}px`, height: `${height}px` }"
:class="[`toast-content`, `toast-text-${type}`, position]"
v-if="ifShow"
>
<span :class="[`icon`, `${getIconClass}`, `iconfont`]"></span>
<span class="text">{{ text }}</span>
<span class="close iconfont icon-cancel1" @click="closeToast"> </span>
</div>
</transition>
</template>

关于css代码,介绍一下iconfont字体图标库的使用

https://www.iconfont.cn/ 添加相关图标到项目中,在资源管理->我的项目中可以看到自己添加的图片,复制那段css代码,就可以在html中通过div class="iconfont icon-cancel1"的方式使用字体图标了,本插件的字体图标也是来源于此。

封装插件

Vue通过Vue.use(plugin)使用插件,它会调用插件中暴露的install方法,下面是index.js,其大致逻辑就是

  • 通过Vue.extend构造组件的实例
  • 将调用方法挂载到Vue的原型上
  • 创建实例时将组件挂载到文档流中
1
2
3
4
5
6
7
8
9
10
11
12
13
import Toast from "./component/index.vue"
export default {
install(Vue, Options) {
let ToastConstructor = Vue.extend(Toast) // 获取toast构造实例
Vue.prototype.$toast = toast; // 将toast的调用封装成一个方法,挂载到Vue的原型上

function toast(args) {
// 传入参数、实例化组件、挂在
const instance = new ToastConstructor({ propsData: args });
document.body.append(instance.$mount().$el)
}
}
}

最后在mian.js中引入并使用

1
2
import toast from './index.js'
Vue.use(toast)

打包发布

这里我将所有插件代码全部汇聚到了export.js中,然后在webpack.config.js中,将发布的入口文件写成export.js就可以了,这里推荐使用Vue官方的打包模板:https://github.com/vuejs-templates/webpack-simple

1
vue init webpack-simple your-project

export.js

1
2
import App from './index.js'
export default App
1
entry: process.env.NODE_ENV === 'development' ? './src/main.js' : './src/export.js',

打包完成之后,就可以发布了,发布有以下几个步骤:

1
2
3
4
5
# 注册npm官方账号
# 登录账号
npm login
# 发布
npm publish

需要注意的是,package.json中的name不能和npm仓库中的重名,不然打包一定会失败的。上传成功后,我们会在个人仓库看到编写的插件。

发布成功截图

个人仓库截图

接着可以通过npm下载使用了

1
npm install -S toast-arch

引入插件

1
2
import toast from 'toast-arch'
Vue.use(toast)

使用插件

1
2
3
4
5
6
7
8
9
10
11
this.$toast({
text: "新消息提示",
width: 200,
height: 60,
autoClose: false,
type: "warning",
position: "topRight",
callback: function () {
console.log(" THis is Callback ");
},
});

Reference

https://juejin.cn/post/6844903989700476941

https://github.com/weirui88888/webpack-simple

https://www.newarray.vip/mabushao/#/dashboard

https://zhuanlan.zhihu.com/p/103426727

https://cn.vuejs.org/v2/guide/components-props.html

https://www.cnblogs.com/luozhihao/p/7414419.html

https://cn.vuejs.org/v2/guide/plugins.html#%E5%BC%80%E5%8F%91%E6%8F%92%E4%BB%B6