“ 在 vue 中自定义实现插件的两种方式简介,附源码。本文大约 1300 字”
目录
什么是自定义插件?
像惯常使用过的 axios、vue-router、vuex、element-ui、vant 等,这些都是插件。插件可以视为从外部引入的,封装好的,功能较为完备的功能性组件库。
翻看 vant 源码,在 src/index.ts 中有这样的代码:
...
const install = (Vue: VueConstructor) => {
components.forEach(Component => {
Vue.use(Component);
});
};
...
export default {
install,
version
};
install 是 vant 向外暴露的方法,当消费者代码在外部调用 Vue.use(vant) 时,实则执行了 install 方法。
vue 规定,插件应该有一个 install 方法。但在业务项目中,除了 install 方法,还有更为直接的实现方式。
01 install + use
src/componnts/Bus/index.js:
// 用于在各组件间自由的事件传递
const install = function (Vue) {
if (!Vue.prototype.$bus){
const Bus = new Vue({
methods: {
emit(event, ...args) {
this.$emit(event, ...args);
},
on(event, callback) {
this.$on(event, callback);
},
off(event, callback) {
this.$off(event, callback);
}
}
});
Vue.prototype.$bus = Bus;
}
};
export default install
这是一个非常简单的事件总线“插件”。在 main.js 中这样启用它:
import Bus from "./components/Bus";
Vue.use(Bus);
这是标准的实现方方式。只需全局注册一次,便可以随处使用,例如消费者代码如下所示:
<van-button @click="handleClick1"
type="default">默认按钮</van-button>
随机数字:{{randNum}}
...
methods: {
handleClick1(){
let rand = Math.floor(Math.random() * 100 + 1) ;
this.$bus.emit("add" , rand) ;
}
}
...
mounted(){
this.$bus.on("add" , (val) => {
this.randNum = val ;
})
}
运行效果:
在这个代码中,事件“add”的监听与广播,均是在一个 vue 组件中,事实上在不同的组件中也可以。
这种插件实现的方式,适用可以全局注册的组件。对于那些不适合污染全局对象的组件,每次都先 import 再调用 Vue.use(xx) 是一种很麻烦的事。如果是 UI 组件,还要在 components 中显式声明,太麻烦了。
有另外一种方式更为直接。
02 extend+appendChild
首先在 vue 文件中定义 template,src/components/Toast/index.vue:
<template>
<div style="...">
<div style="...">{{message}}</div>
</div>
</template>
然后是 src/components/Toast/index.js:
import Vue from 'vue'
import CustomComponent from './index.vue'
const CustomConstructor = Vue.extend(CustomComponent)
export function show(text, duration=2000){
const dom = new CustomConstructor({
el: document.createElement('div'),
data(){
return{
message: text,
show: true
}
}
})
document.body.appendChild(dom.$el)
setTimeout(() => {
document.body.removeChild(dom.$el)
}, duration);
}
原理很简单,就是通过 Vue.extend 扩展出自定义组件的构造器,然后在运行时创建组件,并通过 document.appendChild 添加进渲染列表中去。
这样消费:
<van-button @click="handleClick2"
type="default">触发自定义toast</van-button>
...
import {show as showToast} from '../../components/Toast';
handleClick2(){
showToast('haha');
}
运行效果:
直接通过 import 引用,然后消费,相比第一种方式简单多了。
这种方式适合在业务项目中自定义组件,可以写在本项目中,也可以另写在其它项目中,然后引入进来。
本文涉及的代码可以在这里查看、下载:
https://git.code.tencent.com/shiqiaomarong/simplevue/tree/master/vant-demo/base
下载源码,执行下面的指令便可以查看运行效果:
yarn
yarn serve
参考链接:
— END —