提供11个字段对dialog组件进行控制:
modelValue: 对话框显示隐藏控制,
width: 控制对话框的宽度,
height:控制对话框的高度,
top: 控制对话框个距离顶部的距离,
title: 控制对话框的标题,
appendToBody: 是否将对话框添加至body,
closeOnClickModal: 是否点击遮罩层关闭抽屉,
showConfirm: 是否显示确认按钮,
showCancel: 是否显示取消按钮,
cancelText: 取消按钮的文本,
confirmText: 确认按钮的文本
dialog.vue代码如下
<template>
<teleport v-if="appendToBody" to="body">
<transition name="dialog-fade">
<div v-show="visible" class="dialog-overlay" @click.self="handleCloseModal">
<div class="dialog-content" :style="dialogStyle" @click.stop>
<div class="dialog-header">
<div class="title-content">
<span>{{ title }}</span>
</div>
</div>
<div class="mes-dialog-layout-main">
<slot></slot>
</div>
<div class="dialog-btn">
<div v-if="showCancel" class="dialog-button" @click="handleCancel">{{ cancelText }}</div>
<div v-if="showConfirm" class="dialog-button" @click="handleSure">{{ confirmText }}</div>
</div>
</div>
</div>
</transition>
</teleport>
<transition name="dialog-fade" v-else>
<div v-show="visible" class="dialog-overlay" @click.self="handleCloseModal">
<div class="dialog-content" :style="dialogStyle" @click.stop>
<div class="dialog-header">
<div class="title-content">
<span>{{ title }}</span>
</div>
</div>
<div class="mes-dialog-layout-main">
<slot></slot>
</div>
<div class="dialog-btn">
<div v-if="showCancel" class="dialog-button" @click="handleCancel">{{ cancelText }}</div>
<div v-if="showConfirm" class="dialog-button" @click="handleSure">{{ confirmText }}</div>
</div>
</div>
</div>
</transition>
</template>
<script lang="ts" setup>
import { ref, watch, computed } from "vue";
const props = withDefaults(
defineProps<{
modelValue?: boolean;
width?: string;
height?: string;
top?: string;
title?: string;
appendToBody?: boolean;
closeOnClickModal?: boolean;
showConfirm?: boolean;
showCancel?: boolean;
cancelText?: string;
confirmText?: string;
}>(),
{
modelValue: false,
width: "30%",
height: "auto",
top: "10%",
title: "",
appendToBody: true,
closeOnClickModal: false,
showConfirm: true,
showCancel: true,
cancelText: "取消",
confirmText: "确认"
}
);
const emit = defineEmits<{
(event: "update:modelValue", value: boolean): void;
(event: "beforeClose"): void;
(event: "on-cancel"): void;
(event: "on-sure"): void;
}>();
const visible = ref(props.modelValue);
watch(
() => props.modelValue,
newVal => {
visible.value = newVal;
}
);
const dialogStyle = computed(() => ({
width: props.width,
height: props.height,
marginTop: props.top
}));
function handleCloseModal() {
if (props.closeOnClickModal) {
handleClose();
}
}
function handleClose() {
emit("beforeClose");
emit("update:modelValue", false);
}
function handleCancel() {
emit("on-cancel");
}
function handleSure() {
emit("on-sure");
}
</script>
<style lang="scss" scoped>
.dialog-overlay {
position: fixed;
inset: 0;
z-index: 9999;
height: 100%;
background-color: rgba(0, 0, 0, 0.7);
overflow: auto;
.dialog-content {
position: relative;
margin: 0 auto;
background: #333333;
border-radius: 2px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
box-sizing: border-box;
padding: 16px;
overflow-wrap: break-word;
.dialog-header {
display: flex;
align-items: center;
justify-content: space-between;
height: 56px;
padding: 0 16px;
border-bottom: 1px solid #efefef;
color: #ffffff;
}
.mes-dialog-layout-main {
padding: 16px;
box-sizing: border-box;
flex: 1;
color: #ffffff;
}
.dialog-btn {
display: flex;
justify-content: flex-end;
padding: 10px;
.dialog-button {
margin-left: 10px;
display: inline-flex;
justify-content: center;
align-items: center;
line-height: 1;
height: 32px;
white-space: nowrap;
cursor: pointer;
color: #fff;
text-align: center;
box-sizing: border-box;
outline: 0;
transition: 0.1s;
font-weight: 500;
-webkit-user-select: none;
user-select: none;
vertical-align: middle;
-webkit-appearance: none;
background-color: #2478f2;
border: 1px solid #dcdfe6;
border-color: #2478f2;
padding: 8px 15px;
font-size: 14px;
border-radius: 4px;
}
}
}
}
</style>
<style>
.dialog-fade-enter-active,
.dialog-fade-leave-active {
transition: opacity 0.3s ease;
}
.dialog-fade-enter,
.dialog-fade-leave-to {
opacity: 0;
}
</style>
使用方式:
<template>
<Dialog
v-model="showDialog"
width="500px"
title="对话框"
@before-close="dialogBeforeClose"
@on-sure="handleDialogSure"
@on-cancel="handleDialogCancel"
>
<p>This is the dialog content</p>
</Dialog>
</template>
<script setup lang="ts">
import { ref } from "vue";
import Dialog from "@/components/Dialog/index.vue";
const showDialog= ref(false);
const handleShowDetails = () => {
console.log("跳转到详情页");
showDialog.value = true;
};
const dialogBeforeClose = () => {
console.log("对话框关闭前");
showDialog.value = false;
};
const handleDialogSure = () => {
console.log("对话框确认");
showDialog.value = false;
};
const handleDialogCancel = () => {
console.log("对话框取消");
showDialog.value = false;
};
</script>