在学习之前,先问问自己,为什么要编写vue的插件。
在一个项目中,尤其是大型项目,有很多部分需要复用,比如加载的loading动画,弹出框。如果一个一个的引用也稍显麻烦,而且在一个vue文件中引用的组件多了,会显得代码臃肿,所以才有了封装vue插件的需求。
说完需求,就来看看具体实现。目前我尝试了两种不一样的插件编写的方法,逐个介绍。
这是我的项目目录,大致的结构解释这样,尽量简单,容易理解。
一个是loading插件,一个是toast插件,不同的地方在于:loading插件是作为组件引入使用,而toast插件是直接添加在挂载点里,通过方法改变状态调用的。
目前使用起来是酱紫的:
toast插件
toast文件下有两个文件,后缀为vue的文件就是这个插件的骨架,js文件一个是将这个骨架放入Vue全局中,并写明操作逻辑。
可以看一下toast.vue的内容:
这里面主要的内容只有两个,决定是否显示的show
和显示什么内容的message
。
粗看这里,有没有发现什么问题?
这个文件中并没有props
属性,也就是无论是show也好,message也好,就没有办法通过父子组件通信的方式进行修改,那他们是怎么正确处理的呢。别急,来看他的配置文件。
index.js:
// 注册Toast
Toast.install = function (Vue) {
// 生成一个Vue的子类
// 同时这个子类也就是组件
const ToastConstructor = Vue.extend(ToastComponent)
// 生成一个该子类的实例
const instance = new ToastConstructor();
// 将这个实例挂载在我创建的div上
// 并将此div加入全局挂载点内部
instance.$mount(document.createElement('div'))
document.body.appendChild(instance.$el)
// 通过Vue的原型注册一个方法
// 让所有实例共享这个方法
Vue.prototype.$toast = (msg,duration = 2000) => {
instance.message = msg;
instance.show = true;
setTimeout(() => {
instance.show = false;
},duration);
}
}
export default Toast
这里的逻辑大致可以分成这么几步:
创建一个空对象,这个对象就是日后要使用到的插件的名字。此外,这个对象中要有一个install的函数。使用vue的extend方法创建一个插件的构造函数(可以看做创建了一个vue的子类),实例化该子类,之后的所有操作都可以通过这个子类完成。之后再Vue的原型上添加一个共用的方法。
这里需要着重提的是Vue.extend()
。举个例子,我们日常使用vue编写组件是这个样子的: