插件的作用
插件通常用来为 Vue 添加全局功能。插件的功能范围没有严格的限制——一般有下面几种:
-
添加全局方法或者 property。如:vue-custom-element
-
添加全局资源:指令/过滤器/过渡等。如 vue-touch
-
通过全局混入来添加一些组件选项。如 vue-router
-
添加 Vue 实例方法,通过把它们添加到
Vue.prototype
上实现。 -
一个库,提供自己的 API,同时提供上面提到的一个或多个功能。如 vue-router
使用插件
通过全局方法 Vue.use()
使用插件。它需要在你调用 new Vue()
启动应用之前完成
import MyPlugin from '...'
// 调用 `MyPlugin.install(Vue)`
Vue.use(MyPlugin)
new Vue({
// ...组件选项
})
也可以传入一个可选的选项对象:
Vue.use(MyPlugin, { someOption: true })
如何编写一个插件
Vue.js 的插件应该暴露一个 install
方法。这个方法的第一个参数是 Vue
构造器,第二个参数是一个可选的选项对象:
MyPlugin.install = function (Vue, options) {
// 1. 添加全局方法或 property
Vue.myGlobalMethod = function () {
// 逻辑...
}
// 2. 添加全局资源
Vue.directive('my-directive', {
bind (el, binding, vnode, oldVnode) {
// 逻辑...
}
...
})
// 3. 注入组件选项
Vue.mixin({
created: function () {
// 逻辑...
}
...
})
// 4. 添加实例方法
Vue.prototype.$myMethod = function (methodOptions) {
// 逻辑...
}
}
下面以封装一个全局的loading组件封装成插件为例
loading.vue组件
<template>
<div class="loading-box" v-show="show">
<div class="loading-content">
<a-spin :tip="text"></a-spin>
</div>
</div>
</template>
<script>
export default {
name: "Loading",
props: {
show: {
type: Boolean,
default: false,
},
text: {
type: String,
default: "正在加载中...",
},
},
};
</script>
<style lang="less" scoped>
.loading-box {
position: fixed;
top: 0;
right: 0;
left: 0;
bottom: 0;
background-color: rgba(255, 255, 255, 0.5);
z-index: 10;
.loading-content {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
</style>
封装插件之前使用:
<template>
<div>
<loading :show="true"></loading>
</div>
</template>
<script>
import Loading from './loading.vue'
export default {
...
components: {
Loading
}
...
}
</script>
封装之前只能通过import的方式引入到需要的页面使用,这样有点局限,如果能在页面直接通过this.$loading.open()的方式使用那就方便多了。实现方式就是把loading组件封装成插件,将组件注入到vue全局。
封装LoadingPlugin
import Loading from './Loading.vue'
let $vm
export default {
// 核心: Vue.js 的插件应该暴露一个 install 方法。
// 这个方法的第一个参数是 Vue 构造器,第二个参数是一个可选的选项对象:
install(Vue, options) {
// Vue.use(plagin, options)
console.log('LoadingPlugin options..........', options);
if (!$vm) {
// Vue.extend(Loading) 创建一个“子类”。
const LoadingPlugin = Vue.extend(Loading);
// 挂载loading组件实例
$vm = new LoadingPlugin({
el: document.createElement('div')
});
// 将loading组件追加到页面上
document.body.appendChild($vm.$el);
}
$vm.show = false;
let loading = {
open(text) {
$vm.show = true;
$vm.text = text;
},
close() {
$vm.show = false;
}
};
if (!Vue.$loading) {
Vue.$loading = loading;
}
// 全局混入的方式注入组件选项
Vue.mixin({
created() {
this.$loading = Vue.$loading;
}
})
}
}
使用:
在main.js文件里用Vue.use()注册插件
// main.js
import LoadingPlugin from '@/components/Loading/Loading.js'
Vue.use(LoadingPlugin, { loading: true})
注册完成后就可以页面这样用
openLoadig() {
this.$loading.open("正在加载中...");
setTimeout(() => {
this.$loading.close();
}, 3000);
},
或者可以在请求拦截中配置loading
import Vue from 'vue'
import axios from 'axios'
const service = axios.create({
timeout: 60000,
});
// 错误处理
const httpErr = (error) => {
...
return Promise.reject(error)
}
// resquest interceptor
service.interceptors.request.use(config => {
// 根据需要打开loading
if (config.loading) {
Vue.$loading.open();
}
return config
}, httpErr)
// response interceptor
service.interceptors.response.use(response => {
Vue.$loading.close();
return response.data
}, httpErr)
export { service as axios }