Vue.extend开发全局组件,可通过js直接调用方法来显示和关闭
Vue.extend
是一个全局Api,平时我们在开发业务的时候很少会用到它,但有时候我们希望可以开发一些全局组件比如Loading
,Notify
,Message
等组件时,这时候就可以使用Vue.extend,
extend创建的是一个组件构造器,而不是一个具体的组件实例
本文以开发个全局的loading加载组件为例,实现全局的遮罩层,并且实现通过js直接调用方法来控制组件显示和关闭,而不是通过components关键字来塞到每个vue文件里使用。
一、开发全局需要展示的组件,实现基本功能
<template>
<transition name="custom-loading-fade">
<!--loading遮罩层-->
<div v-show="visible" class="custom-loading-mask">
<!--loading中间的图标-->
<div class="custom-loading-spinner">
<i class="custom-spinner-icon"></i>
<!--loading上面显示的文字-->
<p class="custom-loading-text">{{ text }}</p>
</div>
</div>
</transition>
</template>
<script>
//这里如果是作为components插入到vue文件里一般需要设置为props传值,但是本方法是通过extend,用data定义这些变量即可,不需要用props实现父子传值
/*
export default {
props: {
// 是否显示loading
visible: {
type: Boolean,
default: false
},
// loading上面的显示文字
text: {
type: String,
default: ''
}
}, */ //上部分代码已经屏蔽
data() {
return {
text: '',
visible: false
}
}
}
</script>
二、新建loading.js文件,利用vue.extend改造上面的组件
//新建一个loading.js文件
其主要思路是:
1、引入vue
import Vue from 'vue'
2、引入组件
import alert from '../components/commons/alert/index.vue'
3、扩展vue,生成构造函数
const alertBox = Vue.extend(alert)
4、声明函数 传入options
function alertBoxx (options){
5、new一个新对象
var alert = new alertBox({
6、创建el
el:document.createElement('div'),
7、添加数据
data(){
return{
Obj:{
isshow:true,
message:options.content,
btns:{
confirm:true,
cancel:true
}
}
}
},
8、添加方法
methods:{
confirm:options.callback
}
})
9、获取body 并将元素添加到body
document.querySelector('body').appendChild(alert.$el)
Vue.nextTick(()=>{
alert.Obj.isshow= true
})
}
10、挂载到vue 并暴露
function install(){
Vue.prototype.$alert= alertBoxx
}
export default install
import Vue from 'vue'
import LoadingComponent from './loading.vue'
// 通过Vue.extend将组件包装成一个子类,返回一个构造函数
const LoadingConstructor = Vue.extend(LoadingComponent)
//这上面三行都是固定的套路,引入文件,设置构造函数
let loading = undefined
LoadingConstructor.prototype.close = function() {
// 如果loading 有引用,则去掉引用
if (loading) {
loading = undefined
}
// 先将组件隐藏
this.visible = false
// 延迟300毫秒,等待loading关闭动画执行完之后销毁组件
setTimeout(() => {
// 移除挂载的dom元素
if (this.$el && this.$el.parentNode) {
this.$el.parentNode.removeChild(this.$el)
}
// 调用组件的$destroy方法进行组件销毁
this.$destroy()
}, 300)
}
const Loading = (options = {}) => {
// 如果组件已渲染,则返回即可
if (loading) {
return loading
}
// 要挂载的元素
const parent = document.body
// 组件属性
const opts = {
text: '',
...options
}
// 通过构造函数初始化组件 相当于 new Vue()
const instance = new LoadingConstructor({
el: document.createElement('div'),
data: opts
})
// 将loading元素挂在到parent上面
parent.appendChild(instance.$el)
// 显示loading
Vue.nextTick(() => {
instance.visible = true
})
// 将组件实例赋值给loading
loading = instance
return instance
}
Vue.prototype.$loading = Loading //这绑定的目的是为了在任何地方可以使用 this.$loading()
export default Loading
三、入口js文件中,全局注册
import customLoading from './loading.js'
Vue.use(customLoading )
四、使用
this.$loading() //即可调用出Loading.vue的文件