通过v-model二次封装组件el-dialog组件
//父组件
import { ref } from 'vue';
import type { Ref } from 'vue';
const dialogVisible: Ref<boolean> = ref(false);
function handleClose(done: Function):void {
ElMessageBox.confirm('Are you sure to close this dialog?')
.then(():void => {
done();
})
.catch(():void => {
// catch error
});
}
<AiDialog
v-model="dialogVisible"
:destroy-on-close="false"
:before-close="handleClose"
close-on-press-escape
close-on-click-modal
></AiDialog>
//子组件
<script setup lang="ts">
import { computed } from 'vue';
import { IStyleComputed } from '../utils/type';
const emit = defineEmits(['update:modelValue']);
// interface IProps {
// title: string;
// }
// const props = withDefaults(defineProps<IProps>(), {});
const props = defineProps({
// 开关
modelValue: {
type: Boolean,
required: true,
},
// 标题
title: {
type: String,
default: '标题',
},
// 宽度
width: {
type: String,
default: '30%',
},
// 是否全屏
fullscreen: {
type: Boolean,
default: false,
},
// marginTop的默认值
top: {
type: String,
defalut: '15vh',
},
// 是否需要遮罩
modal: {
type: Boolean,
default: true,
},
// 是否插入body元素上
appendToBody: {
type: Boolean,
default: true,
},
// 开启时是否锁定滚动条
lockScroll: {
type: Boolean,
default: true,
},
// 自定义class类
class: {
type: String,
default: '',
},
// Dialog 打开的延时时间,单位毫秒
openDelay: {
type: Number,
default: 0,
},
// Dialog 关闭的延时时间,单位毫秒
closeDelay: {
type: Number,
default: 0,
},
// 是否可以通过点击 modal 关闭 Dialog
closeOnClickModal: {
type: Boolean,
defalut: false,
},
// 是否可以通过按下 ESC 关闭 Dialog
closeOnPressEscape: {
type: Boolean,
defalut: false,
},
// 是否显示关闭按钮
showClose: {
type: Boolean,
default: true,
},
// 可拖拽
draggable: {
type: Boolean,
default: true,
},
// 是否让 Dialog 的 header 和 footer 部分居中排列
center: {
type: Boolean,
default: false,
},
// 垂直居中
alignCenter: {
type: Boolean,
default: true,
},
// 是否销毁
destroyOnClose: {
type: Boolean,
defalut: false,
},
// 背景颜色
backgroundColor: {
type: String,
default: 'white',
},
// 边框阴影
boxShadow: {
type: String,
default:
'0px 12px 32px 4px rgba(0, 0, 0, .04), 0px 8px 20px rgba(0, 0, 0, .08)',
},
// 头部样式
headerStyle: {
type: Object,
default: {
padding: '20px',
},
},
// 内容区域样式
mainStyle: {
type: Object,
default: {
padding: '30px 20px',
},
},
// 底部区域样式
footerStyle: {
type: Object,
default: {
padding: '20px',
textAlign: 'right',
},
},
//关闭函数
beforeClose: {
type: Function,
},
});
const styleComputed = computed<IStyleComputed>(() => {
return {
backgroundColor: props.backgroundColor,
boxShadow: props.boxShadow,
};
});
const dialogVisibleComputed = computed({
get() {
return props.modelValue;
},
set(val) {
emit('update:modelValue', val);
},
});
// 打开
function open(): void {
// console.log('打开');
}
// 打开动画结束时
function opened(): void {
// console.log('动画结束');
}
// 关闭
function close(): void {
// console.log('关闭');
}
// 关闭动画结束时
function closed(): void {
// console.log('关闭动画结束时');
}
// 输入焦点聚焦在 Dialog 内容时的回调
function openAutoFocus(): void {
// console.log('输入焦点聚焦在 Dialog');
}
// 输入焦点从 Dialog 内容失焦时的回调
function closeAutoFocus(): void {
// console.log('输入焦点从 Dialog 内容失焦时的回调');
}
// 关闭前的回调,会暂停 Dialog 的关闭. 回调函数内执行 done 参数方法的时候才是真正关闭对话框的时候.
function beforeCloseFn(done: Function): void {
if (props.beforeClose) {
props.beforeClose(done);
} else {
done();
}
}
</script>
<template>
<!-- 封装对话框组件 -->
<el-dialog
v-model="dialogVisibleComputed"
:title="props.title"
:width="props.width"
:fullscreen="props.fullscreen"
:top="props.top"
:modal="props.modal"
:append-to-body="props.appendToBody"
:lock-scroll="props.lockScroll"
:class="props.class"
:open-delay="props.openDelay"
:close-delay="props.closeDelay"
:close-on-click-modal="props.closeOnClickModal"
:close-on-press-escape="props.closeOnPressEscape"
:show-close="props.showClose"
:draggable="props.draggable"
:center="props.center"
:align-center="props.alignCenter"
:destroy-on-close="props.destroyOnClose"
:before-close="beforeCloseFn"
@open="open"
@opened="opened"
@close="close"
@closed="closed"
@open-auto-focus="openAutoFocus"
@close-auto-focus="closeAutoFocus"
:style="styleComputed"
>
<template #header>
<div :style="props.headerStyle">
<slot name="header">{{ props.title }}</slot>
</div>
</template>
<div :style="props.mainStyle">
<slot><span>This is a message</span></slot>
</div>
<template #footer>
<div :style="props.footerStyle">
<slot name="footer">
<span class="dialog-footer">
<el-button @click="emit('update:modelValue', !props.modelValue)"
>Cancel</el-button
>
<el-button
type="primary"
@click="emit('update:modelValue', !props.modelValue)"
>
Confirm
</el-button>
</span></slot
>
</div>
</template>
</el-dialog>
</template>
<style scoped lang="scss"></style>
<style lang="scss">
.el-dialog__header {
padding: 0;
// margin-right: 0;
}
.el-dialog__body {
padding: 0;
}
.el-dialog__footer {
padding: 0;
text-align: unset;
}
</style>
以上!