在新公司发现弹框是基于 element 改造,但是是依然需要引入组件,设置变量来控制显示隐藏。
对比之前公司,基于 vxe-table 组件的 modal 组件二次封装,在使用时,只需要引用然后调用打开或关闭某个方法
所以,对比二者,简单封装个 demo
参数
按照常用的弹框需求,常见的情形大概有
- 只显示弹窗内容
- 需要传值给弹框内部组件
- 弹窗的宽高,标题的对应参数
- 弹窗向外抛出事件
所以在调用时设置参数有:
component 引用的组件
props 传递给 component 的值
options el-dialog 的参数
event 回调的事件
代码
import modal from '../components/modal/index.js' // 弹框组件
import modalContent from '../components/modal/modal-content' // 弹框里面的内容组件
modal.open({
component: modalContent,
props:{
sendModalVal:'传递给弹窗的值'
},
options: {
title: '消息提示',
}},{
close(name) {
console.log('我关闭了')
modal.close(name)
},
changeNum(val) {
console.log('是我来自弹框组件的值',val)
}
})
index.js 组件挂载到 dom 上,重点$mount()方法
// WModal.js
import Vue from 'vue';
// 具体的组件
import WModal from './modal.vue';
WModal.newInstance = properties => {
const props = properties || {};
// 实例化一个组件,然后挂载到 body 上
const Instance = new Vue({
data: props,
render(h) {
return h(WModal, {
props: props
});
}
});
const component = Instance.$mount();
document.body.appendChild(component.$el);
// 通过闭包维护 modal 组件的引用
const modal = Instance.$children[0];
return {
// modal 组件对外暴露的两个方法
add(modalProps, event) {
modal.add(modalProps, event);
},
remove(name) {
modal.remove(name);
}
}
};
// 提示单例
let messageInstance;
function getMessageInstance() {
messageInstance = messageInstance || WModal.newInstance();
return messageInstance;
}
function open({ component, props, options = {title:'提示'}}, event) {
// 等待接口调用的时候再实例化组件,避免进入页面就直接挂载到 body 上
let instance = getMessageInstance();
instance.add({
component,
props,
options
}, event)
}
function close(id = '') {
// 等待接口调用的时候再实例化组件,避免进入页面就直接挂载到 body 上
let instance = getMessageInstance();
instance.remove(id)
}
// 对外暴露的方法
let modal = {
open(params, event) {
return open(params, event);
},
close(name) {
return close(name);
}
}
export default modal
modal.vue 组件 template,将每个 modal 对象遍历出来,重点:v-on 和 v-bind
<template>
<div class='modal'>
<div class='modal-main' v-for='item in modals' :key='item.id'>
<el-dialog
:visible='true'
v-on='item.event'
v-bind='item.options'
@close='remove(item.id)'
>
<span>{{ item.id }}</span>
<component :is='item.component' :id='item.id' v-bind='item.props' v-on='item.event'></component>
<span slot='footer' class='dialog-footer'>
<el-button @click='remove(item.id)'>取 消</el-button>
<el-button type='primary' @click='remove(item.id)'>确 定</el-button>
</span>
</el-dialog>
</div>
</div>
</template>
<script>
let seed = 0;
function getUuid() {
return 'modal_' + (seed++);
}
export default {
data() {
return {
modals: []
}
},
methods: {
add(modal, event) {
console.log(modal)
const id = getUuid();
let _modal = Object.assign({
id: id,
event
}, modal);
this.modals.push(_modal);
},
remove(id) {
const modals = this.modals;
for (let i = 0; i < modals.length; i++) {
if (modals[i].id === id) {
this.modals.splice(i, 1);
break;
}
}
},
close(id) {
this.$emit('close',id)
}
}
}
</script>
在 modalContent 中,主要是抛出事件,和获取 modal 传来的值
this.sendModalVal=this.$attrs.sendModalVal
this.$emit('changeNum',this.num)