import Vue from 'vue'
import store from '../../store'
import Dialog from '@/views/components/dialog'
let instance
let isExist
const DialogBox = Vue.extend(Dialog)
Dialog.install = (data) => {
if (!data.dom) {
console.log('内容缺失')
return false
}
if (data.coexist) { // 尚持弹框是否保留
isExist = new DialogBox({
data,
store
}).$mount()
document.body.appendChild(isExist.$el)
// 挂载至页面(#app)
Vue.nextTick(() => {
isExist.visible = true
// show 和弹窗组件里的show对应,用于控制显隐
})
} else {
if (isExist) {
isExist.visible = false
document.body.removeChild(isExist.$el)
isExist = null
}
if (instance) {
instance.visible = false
document.body.removeChild(instance.$el)
instance = null
} // 移除已有弹窗,确保只有一个弹窗显示
instance = new DialogBox({
data,
store
}).$mount()
document.body.appendChild(instance.$el)
// 挂载至页面(#mes
Vue.nextTick(() => {
instance.visible = true
// visible 和弹窗组件里的show对应,用于控制显隐
})
}
}
/**
* 简单的使用方式
* this.$dialogPopup({
title: '测试', // 标题的内容
dom: Test, // 组件是自己创建的
width: '800px', // 弹框的宽度
coexist: false, // 控制上一次弹窗是否保留,默认false
option: {} 数据会传入自己的组件 通过props里定义option 组件里可以使用this.option 拿到
})
* 异步用法
this.$dialogPopup({
title: '测试',
dom: Test,
showFooter: true, // 展示脚部组件
isSync: true, // 是否要异步关闭
width: '800px',
coexist: false, // 控制上一次弹窗是否保留,默认false
option: data,
ok: (success) => { // ok 回调的参数是一个函数 调用就可以在接口调用后关闭弹框
setTimeout(() => {
success()
}, 5000)
}
})
* 给内容绑定事件 让组件内的事件能推到组件调用里外头
this.$dialogPopup({
title: '测试',
dom: Test,
width: '800px',
coexist: false, // 控制上一次弹窗是否保留,默认false
option: data,
events: 'content', // 给传递到组件的自定义内容组件绑定content 事件,组件内使用this.$emit('content', data)调用 多个请用数组
content: (data) => { // 定义同名的函数对象其中可以拿到组件对外外传输的值
// data 就是要传递的参数
},
clickContent: (data)=> {
// 组件默认绑定了click事件 自定义内容组件内使用this.$emit('click', data)调用
}
})
* 脚步自定义组件和异步情况下自定义组件的用法
this.$dialogPopup({
title: '测试',
dom: Test,
showFooter: true, // 展示脚部组件
footerDom: TestFooter, // 自定义脚部组件
footerEvents: 'footer', // 自定义脚部事件 多个请用数组
footer: (data, success) => { // 需要定义同名的事件名称 success 是异步情况下第二个参数
setTimeout(() => {
success()
}, 3000)
},
isSync: true, // 开启异步
width: '800px',
coexist: false, // 控制上一次弹窗是否保留,默认false
option: data
})
*/
export default Dialog
dialog
<template>
<common
ref="dialogInstance"
:visible.sync="visible"
:width="popupWidth"
center
:show-close="needClose"
@close="closeDialog"
@closed="closed"
@open="openDialog"
>
<template #title>
<span v-if="title" class="common-dialog-title">{{ title }}</span>
<component
:is="titleDom"
v-if="titleDom"
:option.sync="titleOption"
v-on="dealTitleEvent"
/>
</template>
<component
:is="dom"
:option.sync="option"
v-on="dealEvent"
/>
<template v-if="showFooter" #footer>
<component
:is="footerDom"
v-if="footerDom"
:option.sync="footerOption"
v-on="dealFooterEvent"
/>
<div v-else class="common-dialog-bottom">
<el-button @click="cancelDialog">{{ cancelText }}</el-button>
<el-button type="primary" :loading="loading" @click="okDialog">{{ okText }}</el-button>
</div>
</template>
</common>
</template>
<script>
import Common from '@/views/components/dialog/common.vue'
export default {
name: 'DialogAll',
components: {
Common
},
data() {
return {
visible: false,
title: '',
width: '550px',
showClose: true,
cancelText: '取消',
okText: '确认',
loading: false,
showFooter: false,
isSync: false,
footerDom: null,
titleDom: null,
events: [],
footerEvents: [],
titleEvents: [],
option: null,
titleOption: null,
footerOption: null,
hasClosed: false
}
},
computed: {
popupWidth() {
return this.width || '550px'
},
needClose() {
return this.showClose || true
},
dealEvent() {
let events = this.events
const newEvent = {}
if (Object.prototype.toString.call(events) === '[object String]') {
events = [events]
}
events.forEach(item => {
newEvent[item] = (data) => {
this[item] && this[item](data, () => {
this.visible = false
})
}
})
const eventObject = {
'click': this.clickContent,
...newEvent
}
return eventObject
},
dealTitleEvent() {
let events = this.titleEvents
const newEvent = {}
if (Object.prototype.toString.call(events) === '[object String]') {
events = [events]
}
events.forEach(item => {
newEvent[item] = (data) => {
this[item] && this[item](data, () => {
this.visible = false
})
}
})
const eventObject = {
'close': this.closeDialog,
...newEvent
}
return eventObject
},
dealFooterEvent() {
let footerEvents = this.footerEvents
const newEvent = {}
if (Object.prototype.toString.call(footerEvents) === '[object String]') {
footerEvents = [footerEvents]
}
footerEvents.forEach(item => {
newEvent[item] = (data) => {
if (this[item]) {
if (this.isSync) {
this.loading = true
this[item](data, () => {
this.loading = true
this.visible = false
})
} else {
this.visible = false
this[item](data)
}
}
}
})
const eventObject = {
'click': this.clickFooter,
...newEvent
}
return eventObject
}
},
mounted() {
this.hasClosed = false
},
methods: {
closeDialog() {
this.visible = false
if (this.close) {
this.close()
}
},
clickContent() {
if (this.clickContent) {
this.clickContent()
}
},
clickFooter() {
if (this.clickFooter) {
this.clickFooter()
}
},
openDialog() {
if (this.open) {
this.open()
}
},
cancelDialog() {
// 取消
this.visible = false
if (this.cancel) {
this.cancel()
}
},
okDialog() {
// 确认
if (!this.isSync) {
this.visible = false
}
if (this.ok) {
if (this.isSync) {
this.loading = true
this.ok(() => {
this.loading = true
this.visible = false
})
} else {
this.ok()
}
}
},
closed() {
this.hasClosed = true
}
}
}
</script>
<style lang="scss">
.common-dialog {
.el-dialog {
min-height: 500px;
background: #03151F;
border: 1px solid #2AA8FF;
box-shadow: 0px 1px 18px 0px #2AA8FF,inset 0px 1px 10px 0px #2AA8FF;
color: #fff;
padding: 10px;
.el-dialog__header {
position: relative;
box-sizing: border-box;
padding: 0 14px;
line-height: 60px;
height: 60px;
width: 100%;
background: url(../../../assets/images/alert-bg.png) no-repeat center bottom;
background-size: calc(100% + 20px) calc(100% + 20px);
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
align-items: center;
&::before {
width: 100%;
content: "";
height: 6px;
position: absolute;
left: -11px;
top: -17px;
background: url(../../../assets/images/alert-bg.png) no-repeat left top;
background-size: auto, 8px;
}
.common-dialog-title {
font-size: 16px;
text-align: left;
text-indent: 18px;
position: relative;
&::before {
content: "";
width: 4px;
height: 14px;
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
background: #fff;
}
}
.el-dialog__headerbtn {
top: 50%;
transform: translateY(-50%);
.el-dialog__close {
color: #fff;
transition: all 0.2s;
}
&:hover {
.el-dialog__close {
color: #2AA8FF;
}
}
}
}
.el-dialog__body {
height: 100%;
padding: 0;
color: #fff;
}
}
}
</style>