当前位置: 首页 > news >正文

vue3编程 -动态多开模态框实现方案

 页面按需弹出多个模态框:

 一、v-for方案:

                采用v-for提前生成多个模态框实例,采用这种方案的案例社区已经很多

二、采用h函数方案:

   代码如下,代码可运行:

   基本思路:

1. 封装模态框组件DialogModal

2.通过h()函数创建DialogModal的虚拟dom

3. 通过创建容器元素+vue的mount()函数进行挂载

4. 模态框关闭后需要解除挂载,通过vue的unmoun()函数

如果模态框是自行开发的,到此应该就可以结束了。但是,基于element plus的模态框,会存在当前模态框阻挡后面模态框点击的问题,解决方案如下:

.modal-class {pointer-events: none;
}
.el-overlay-dialog {pointer-events: none;
}
.el-dialog {pointer-events: auto;
}

完整代码如下: 

<script setup lang="ts">
import DialogModal from '@/components/DialogModal.vue'
import { ref, onUnmounted, h, createApp } from 'vue'
import { ElMessage } from 'element-plus'const modals = ref([])const showModal = () => {let num = Math.random()createModal({ title: 'test' + num, showMsg: 'hello' + num })
}const createModal = config => {const modalRef = ref()const modalInstance = h(DialogModal, {ref: modalRef,title: config.title,content: config.showMsg,onClosed: () => {removeModal(modalRef.value)},onConfirmed: () => {removeModal(modalRef.value)ElMessage.success('模态框已关闭')}})console.log('modalInstance', modalInstance)modals.value.push(modalRef)// 创建虚拟 DOM 并挂载到文档const container = document.createElement('div')container.id = 'modal-container' + Math.random()document.body.appendChild(container)const app = createApp(modalInstance)app.mount(container)return {unmount: () => {app.unmount()document.body.removeChild(container)}}
}const removeModal = modal => {if (modal) {modal.unmount()const index = modals.value.findIndex(m => m.component === modal)if (index !== -1) {modals.value.splice(index, 1)}}
}onUnmounted(() => {modals.value.forEach(modal => {modal.component.unmount()})
})
</script><template><div><el-button @click="showModal">显示模态框</el-button></div><router-view></router-view>
</template>
<template><div :class="{ scrollDialog: scrollVisible }"><el-dialogv-model="dialogVisible":width="props.width":destroy-on-close="true":close-on-click-modal="false":modal="false"draggable:z-index="-1":fullscreen="false"@close="closeDialog":modal-class="'modal-class'"><template v-slot:header><span class="cus-title">{{ props.title }}</span></template><slot>{{ props.showMsg }}</slot><template v-slot:footer><span v-if="props.dialogFoot || props.dialogFix" class="dialog-footer"><el-button v-if="props.dialogFoot" @click="closeDialog">{{ cancleName }}</el-button><el-button v-if="props.dialogFix" type="primary" @click="determine">{{ determineName }}</el-button></span></template></el-dialog></div>
</template>
<script setup lang="ts">
import { defineProps, ref, defineExpose, defineEmits } from 'vue'const emits = defineEmits(['determine', 'closeDialog'])const props = defineProps({width: {// 弹框宽度type: String,default: '480px'},title: {// 弹框模块名称type: String,default: () => {return ''}},showMsg: {// 展示的信息type: String,default: ''},dialogFoot: {// 显示取消代码type: Boolean,default: true},dialogFix: {// 显示确定按钮type: Boolean,default: true},determineName: {// 确定键名称type: String,default: '确认'},cancleName: {// 取消键名称type: String,default: '取消'}
})
// 弹框显示状态
let dialogVisible = ref(true)
// 控制滚动条样式,超过10条显示滚动条
let scrollVisible = ref(false)
/*** 打开模态框*/
function openDialog() {if (dialogVisible.value) {return}dialogVisible.value = true
}/*** 关闭模态框*/
function closeDialog() {if (!dialogVisible.value) {return}dialogVisible.value = falseemits('closeDialog') // 用户自定义取消后函数,例如:清空表单数据
}/*** @description: 确定事件* @param null* @return: null*/
function determine() {emits('determine') // 触发组件上的determine事件,用户自定义提交dialogVisible.value = false
}
/*** 对外提供打开和关闭模态框,控制模态框和滚动条的显隐*/
defineExpose({ closeDialog, openDialog, dialogVisible, scrollVisible })
</script>
<style scoped lang="scss">
// @import '@/assets/scss/auditPublic.scss';
.el-dialog__body {padding: 20px;
}
.el-dialog__footer {border-top: 1px solid #e9ebef;
}
.cus-title {width: 100%;text-overflow: ellipsis;white-space: nowrap;overflow: hidden;font-size: 16px;color: #031129;display: inline-block;
}
:deep(.el-transfer .el-transfer-panel__item.el-checkbox) {height: auto !important;
}:deep(.el-dialog__body) {max-height: 400px !important;
}.scrollDialog {:deep(.el-dialog__body) {overflow-y: auto !important;height: 400px !important;}
}
</style>
<style>
.modal-class {pointer-events: none;
}
.el-overlay-dialog {pointer-events: none;
}
.el-dialog {pointer-events: auto;
}
</style>


http://www.mrgr.cn/news/13639.html

相关文章:

  • MySQL中的事务
  • [英语单词] unsound
  • 19行为型设计模式——备忘录模式
  • Uniapp 调用aar、jar包
  • 学习笔记——Redis基础
  • ★ 算法OJ题 ★ 力扣1089 - 复写零
  • Java 结合elasticsearch-ik分词器,实现评论的违规词汇脱敏等操作
  • 2024.8.28 作业
  • Spring:浅谈对Spring的认识
  • 【微信小程序】全局数据共享 - MobX
  • 【学习笔记】 陈强-机器学习-Python-Ch13 提升法(1)
  • 云计算环境下的数据治理
  • 光性能 -- 光功率平坦度
  • 【计算机网络】mini HTTP服务器框架与代码
  • XR虚拟拍摄短剧 | 探索虚拟制作在短剧领域的应用与发展
  • 今日算法:蓝桥杯基础题之“门牌制作”
  • Python 正则表达式
  • 掌握PyTorch模型的版本控制:高效管理与迭代
  • 乐凡三防:工业界的硬核产品——重新定义三防平板的极限
  • Nginx 负载均衡深入指南:`proxy_pass` 指令的高效使用