1、自定义customDialog.vue
<template>
<div class="custom-modal"
:style="{ top: customStyle.y + 'px', left: customStyle.x + 'px', zIndex: modalConfig.zde }"
@mousedown="mouseDown" v-if="modalConfig.visible">
<div class="title">
<span>新增</span>
<el-popconfirm title="确认关闭弹窗吗" :hide-icon="true" @confirm="closed">
<template #reference>
<el-icon>
<Close />
</el-icon>
</template>
</el-popconfirm>
</div>
<slot name="content"></slot>
</div>
</template>
<script lang="ts" setup>
import { defineProps, watch, withDefaults, ref } from 'vue';
import { Close } from '@element-plus/icons-vue'
interface Props {
modalConfig: any
}
const prop = withDefaults(defineProps<Props>(), {
modalConfig: () => {
return {
posit: { x: 0, y: 0 },
visible: false,
id: 0,
zde: 100
}
}
})
const emit = defineEmits<{ closed: [value: any], onActive: [value?: any] }>()
let customStyle = ref({
x: 0,
y: 0
})
let offset = ref({ x: 0, y: 0 })
watch(() => prop.modalConfig.posit, (newValues) => {
if (newValues) {
customStyle.value = newValues
}
})
const mouseDown = (e: any) => {
emit('onActive')
offset.value = {
x: e.clientX - customStyle.value.x,
y: e.clientY - customStyle.value.y,
}
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
}
const onMouseMove = (e: any) => {
customStyle.value.x = e.clientX - offset.value.x
customStyle.value.y = e.clientY - offset.value.y
}
const onMouseUp = (e: any) => {
document.removeEventListener('mousemove', onMouseMove)
document.removeEventListener('mouseup', onMouseUp)
}
const closed = () => {
emit('closed', prop.modalConfig.id)
}
</script>
<style scoped lang="scss">
.custom-modal {
min-width: 400px;
min-height: 300px;
position: fixed;
background-color: white;
box-shadow: 2px 2px 11px 12px rgba(160, 160, 160, 0.1);
.title {
height: 48px;
background-color: #096349;
display: flex;
align-items: center;
justify-content: space-between;
color: white;
padding: 0 10px;
}
}
</style>
2.组件中使用
<template>
<div class="app">
<button @click="addModal">新增弹窗</button>
<Modal v-for="(item,index) in modals" :key="item.id" :modal-config="item" @closed="closed" @onActive="changeZindex(item)" style="width: 960px;">
<template #content>
<div class="content">
<p>Modal Content {{ index }}</p>
<p>Modal Content {{ index }}</p>
<p>Modal Content {{ index }}</p>
<p>Modal Content {{ index }}</p>
<p>Modal Content {{ index }}</p>
</div>
</template>
</Modal>
</div>
</template>
<script setup >
import { reactive, ref } from 'vue';
import Modal from './dialog/custom.vue';
const modals = reactive([]);
let id = 0
let activeIndex = ref(0)
const addModal = () => {
modals.push({
posit:{x:0,y:0},
visible:true,
id:id++,
zde:Math.round(Math.random() *10)
})
};
const changeZindex=(item)=>{
item.zde = Math.max(...modals.map((chidItem)=>chidItem.zde)) +10
}
const closed=(id)=>{
modals.splice(modals.findIndex((item)=>item.id === id),1)
}
</script>
<style scoped>
.content{
max-height: 500px;
overflow: auto;
}
</style>