Vue中如何使用自定义插件(plugin)
1、在根目录src下创建一个libs文件夹,在libs文件夹下面创建一个myPlugins文件夹,用来存放我们的自定义插件,在myPlugins文件夹下面再创建一个index.js的文件。
在index.js文件里面,我们创建一个myPlguin的对象,然后导出,最后在
main.js
中导入并且通过use()
的方式使用即可,一个自定义插件便完成了,就是这么简单,好了,感谢大家的阅读。其余的事情就是在myPlugins/index.js
文件里填充我们插件的功能代码了。
2、在libs/myPlugins/index.js文件里创建myPlguin对象并导出,给myPlguin对象添加一个
install
的方法,install
方法的第一个参数是Vue
实例,第二个是我们的配置项options
const myPlguin = {};
myPlguin.install = function (Vue, options) {}
export default myPlguin;
3、接下来就是在main.js文件里引入,并使用
Vue.use()
方法使用。
// 导入并使用我们的自定义插件
import myPLugin from './libs/myPlugin';
Vue.use(myPLugin);
接下来我们聊聊插件里可以做那些事情,这部分才是重点。
1、在自定义插件里面定义我们的全局方法
// 自定义组件里面定义的全局方法
Vue.myGlobalMethod = function () {
console.log('自定义组件里面定义的全局方法');
}
然后我们在main.js文件中使用一下这个全局方法
// 导入并使用我们的自定义插件
import myPLugin from './libs/myPlugin';
Vue.use(myPLugin);
// 使用自定义插件里面的全局方法
Vue.myGlobalMethod();
结果如下图所示:2、在自定义插件里面定义我们的全局自定义指令、过滤器以及全局组件
// 自定义组件里面定义的全局自定义指令
Vue.directive('my-directive', {
bind() {
console.log('自定义组件里面的自定义指令绑定成功');
}
});
在组件中使用自定义指令
"shopList"></digui>
结果如下图所示:3、在自定义插件件里面加入全局混入
Vue.mixin({
// 注入到每个组件的 created 生命周期中
created() {
console.log("created in plugin")
},
})
结果如图所示:4、在自定义插件件里面定义一些实例方法
Vue.prototype.$myMethod = function(){
console.log("自定义组件里面定义的实例方法");
}
这样我们便可在项目中通过this的形式直接调用实例方法。我们在about页面的created生命周期中调用一下这个实例方法
created() {
this.$myMethod();
},
结果如下图所示:
libs/myPlugin/index.js完整代码:
const myPlguin = {};
myPlguin.install = function (Vue, options) {
// 自定义组件里面定义的全局方法
Vue.myGlobalMethod = function () {
console.log('自定义组件里面定义的全局方法');
}
// 自定义组件里面定义的全局自定义指令
Vue.directive('my-directive', {
bind() {
console.log('自定义组件里面的自定义指令绑定成功');
}
});
// 也可以加入全局的过滤器、全局组件
// 加入全局混入
Vue.mixin({
// 注入到每个组件的 created 生命周期中
created() {
console.log("created in plugin")
},
})
// // 定义一些实例方法
Vue.prototype.$myMethod = function(){
console.log("自定义组件里面定义的实例方法");
}
}
export default myPlguin;
那么我们在Vue项目中使用第三方插件时,就通过
Vue.use()
来挂载,如ElementUI,但是axios就不需要,这是为什么呢?因为axios没有install方法。
// 引入ElementUI
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
看看源码
toArray 源码
export function toArray (list: any, start?: number): Array<any> {
start = start || 0
let i = list.length - start
const ret: Array = new Array(i)while (i--) {
ret[i] = list[i + start]
}return ret
}
import { toArray } from '../util/index'
export function initUse (Vue: GlobalAPI) {
Vue.use = function (plugin: Function | Object) {
const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))
if (installedPlugins.indexOf(plugin) > -1) {
return this
}
// additional parameters
const args = toArray(arguments, 1)
args.unshift(this)
if (typeof plugin.install === 'function') {
plugin.install.apply(plugin, args)
} else if (typeof plugin === 'function') {
plugin.apply(null, args)
}
installedPlugins.push(plugin)
return this
}
}
从源码中我们可以发现 vue 首先判断这个插件是否被注册过,不允许重复注册,并且接收的 plugin 参数的限制是 Function | Object 两种类型。对于这两种类型有不同的处理。首先将我们传入的参数整理成数组:
const args = toArray(arguments, 1);
再将 Vue 对象添加到这个数组的起始位置args.unshift(this)
,这里的 this 指向 Vue 对象;如果我们传入的plugin(Vue.use的第一个参数)
的 install 是一个方法。也就是说如果我们传入一个对象,对象中包含 install 方法,那么我们就调用这个 plugin 的 install 方法并将整理好的数组当成参数传入 install 方法中,plugin.install.apply(plugin, args);
如果我们传入的 plugin 就是一个函数,那么我们就直接调用这个函数并将整理好的数组当成参数传入,plugin.apply(null, args);
之后给这个插件添加至已经添加过的插件数组中,标示已经注册过installedPlugins.push(plugin);
最后返回 Vue 对象。
通过以上分析我们可以知道,在我们以后编写插件的时候可以有两种方式。一种是将这个插件的逻辑封装成一个对象,最后将在 install 编写业务代码暴露给 Vue 对象。这样做的好处是可以添加任意参数在这个对象上方便将 install 函数封装得更加精简,可拓展性也比较高。还有一种则是将所有逻辑都编写成一个函数暴露给 Vue。其实两种方法原理都一样,无非第二种就是将这个插件直接当成 install 函数来处理。个人觉得第一种方式比较合理。
export const Plugin = {
install(Vue) {
Vue.component...
Vue.mixins...
Vue...
// 我们也可以在install里面执行其他函数,Vue会将this指向我们的插件
console.log(this) // {install: ...,utils: ...}
this.utils(Vue) // 执行utils函数
console.log(this.COUNT) // 0
},
utils(Vue) {
Vue...
console.log(Vue) // Vue
},
COUNT: 0
}
// 我们可以在这个对象上添加参数,最终Vue只会执行install方法,而其他方法可以作为封装install方法的辅助函数
const test = 'test'
export function Plugin2(Vue) {
Vue...
console.log(test) // 'test'
// 注意如果插件编写成函数形式,那么Vue只会把this指向null,并不会指向这个函数
console.log(this) // null
}
// 这种方式我们只能在一个函数中编写插件逻辑,可封装性就不是那么强了
![23d267d6552634c7e0264b76d5fad43d.png](https://i-blog.csdnimg.cn/blog_migrate/1a5b3b470b5105459471870a32c428c5.png)