ant-design中的Modal组件有两种用法:
第一种是用标签:<a-modal></a-modal>
第二种是用Api:Modal.info、Modal.warning、Modal.confirm......
一开始项目中这两种用法是混用的,后面UI改造,需要统一样式,步骤如下:
1、封装全局弹窗组件 src/components/ConfirmModal/index.vue
<template>
<a-modal
v-model:visible="visible"
:title="props.title"
centered
width="400px"
:footer="null"
:keyboard="false"
:maskClosable="false"
destroyOnClose
@cancel="cancel"
>
<div v-if="vNode" ref="contentRef" class="text-align-c mt-16"></div>
<div v-else class="text-align-c mt-16">{{ description }}</div>
<footer class="text-align-c mb-24 mt-40">
<template v-if="footerVNode1 || footerVNode2">
<a-button v-if="footerVNode1" ref="footerRef1" class="long-btn" @click="cancel"></a-button>
<a-button
v-if="footerVNode2"
ref="footerRef2"
type="primary"
:class="[footerVNode1 ? 'ml-40' : 'ml-0', 'long-btn']"
@click="cancel"
></a-button>
</template>
<template v-else>
<a-button class="long-btn" @click="cancel">取消</a-button>
<a-button class="ml-40 long-btn" type="primary" :loading="btnLoading" @click="confirm">确认</a-button>
</template>
</footer>
</a-modal>
</template>
<script setup>
import { ref, render, nextTick } from 'vue'
import { Button, Modal } from 'ant-design-vue'
const AButton = Button
const AModal = Modal
const emits = defineEmits(['confirm', 'cancel'])
const props = defineProps({
title: {
type: String,
default: '提示'
},
vNode: {
type: Object,
default: null
},
footerVNode1: {
type: Object,
default: null
},
footerVNode2: {
type: Object,
default: null
}
})
const contentRef = ref()
const footerRef1 = ref()
const footerRef2 = ref()
const visible = ref(false)
const description = ref('')
const btnLoading = ref(false)
const openModel = value => {
description.value = value
visible.value = true
nextTick(() => {
if (props.vNode) {
render(props.vNode, contentRef.value)
}
if (props.footerVNode1) {
render(props.footerVNode1, footerRef1.value.$el)
}
if (props.footerVNode2) {
render(props.footerVNode2, footerRef2.value.$el)
}
})
}
const cancel = () => {
btnLoading.value = false
visible.value = false
emits('cancel')
}
const confirm = () => {
emits('confirm')
}
defineExpose({
openModel,
cancel,
btnLoading
})
</script>
<style lang="less" scoped></style>
2、同级目录下新建js文件,调用弹窗组件 src/components/ConfirmModal/index.js
import { createApp } from 'vue'
import ConfirmModal from './index.vue'
export function showConfirmModal(vNode, footerVNode1, footerVNode2) {
const div = document.createElement('div')
document.body.appendChild(div)
const app = createApp(ConfirmModal, { vNode, footerVNode1, footerVNode2 })
const vm = app.mount(div)
vm.openModel()
return { app, vm }
}
3、在需要调用弹窗组件的js文件中引用 xxx.js
import { ref, h } from 'vue'
import { showConfirmModal } from '@/components/ConfirmModal/index.js'
// 强制登录提示
const forceLogin = () => {
localStorage.clear()
showConfirmModal(
h('div', { style: { color: '#333' } }, '你的账号在另一台设备登录,你将被迫下线,请确认密码是否泄露!'),
null,
h(
'div',
{
onClick: () => {
window.location.reload()
}
},
'确认'
)
)
}
4、效果图