之前的文章Vue全局弹出自定义组件_qqq6654066的博客-CSDN博客这里说到可以弹出自定义的页面,但是缺点也比较明显,就是每次想要弹出前都要先导入,可不可以做成想要调用哪个页面就哪个页面,而不需要自己引入呢?说干就干,我们先用json表配置好可能用到的页面,然后用到哪一个,传参过来调用就可以,不用在自己的页面中引入页面文件。
首先配置好json表
{
"components":[
{
"name":"cp1",
"componentsName":"components1"
},
{
"name":"cp2",
"componentsName":"components2"
}
]
}
然后再写两个简单的组件,组件里面就是显示文字不一样,就不重复写了
<template>
<div v-if="isShow" @click="myClick" class="myClas">我是组件1
<div class="myClas2" @click="myClick">确定</div>
</div>
</template>
<script>
export default{
name:'components1',
data(){
return{
isShow:false
}
},
methods:{
myClick(){
// 点击隐藏组件
this.isShow=false
}
}
}
</script>
<style>
.myClas{
position: absolute;
top: 50%;
left: 50%;
z-index: 999;
padding: 10px;
border-radius: 10px;
box-shadow: 0 0 5px #ccc;
}
.myClas2{
margin-top: 10px;
padding-top: 5px;
text-align: center;
font-size: 8px;
border-top: solid 1px #CCCCCC;
}
</style>
然后就是写核心的处理逻辑部分了
import components from './json/options.json'
export default {
// 注册myPop
install(Vue) {
// 使用闭包实现单例模式
var OldCase;
// 接收name和opts,name是组件名,opts是传过去的值
Vue.prototype.$myPop = (name, opts) => {
// 从json表中获取所有配置参数
let myComponents = components.components;
// 遍历json表,寻找相应的组件
myComponents.forEach((item) => {
if (item.name === name) {
// 导入组件
let myCom = import('./' + item.componentsName + '.vue');
myCom.then(res => {
// 生成一个Vue的子类
let MyTpl = Vue.extend(res.default);
// 生成一个该子类的实例
let NewCase = new MyTpl().$mount()
// 如果还没有任何实例就使用新实例
if (OldCase === undefined) {
OldCase = NewCase;
// 如果已经有实例,就清除旧的实例,再使用新的实例
} else if (OldCase.$options.name !== NewCase.$options.name) {
document.body.removeChild(OldCase.$el);
OldCase = NewCase;
}
// 将此div加入全局挂载点内部
document.body.appendChild(OldCase.$el);
// 把传进来的参数传过去组件中
Object.keys(opts).forEach(key => {
OldCase[key] = opts[key];
})
})
}
})
}
}
}
注释上面也写得比较清楚,使用了单例模式,根据传入的组件名在json表中配对,有的话就销毁上一个实例化的组件,并把新的实例挂载到全局中,再把传过来的参数传入组件中去。
然后再把文件挂载到main.js中去
至此就已经完成了,我们试试效果把
新建一个test文件,使用this.$myPop(“name",{isShow:true})来使用
<template>
<div class="my_main">
<button type="button" @click="myClick('cp1')">1</button>
<button type="button" @click="myClick('cp2')">2</button>
</div>
</template>
<script>
export default{
data(){
return{
}
},
methods:{
myClick(com){
this.$myPop(com,{isShow:true})
}
}
}
</script>
<style>
.my_main{
width: 150px;
height: 50px;
justify-content: space-between;
display: flex;
margin: auto auto;
}
button{
width: 50%;
}
</style>
下面这是效果图
因为使用了单例模式,所以不会多次加载组件导致内存溢出的问题
需要源码的小伙伴可以在这里下载