在我们日常开发中,在很多地方都会用到dialog,特别是在一些后台管理系统中,比如新增数据、编辑数据等等 但是有时候由于业务需求的原因,原有的一些框架,比如element-ui中提供的模态框满足不了当前的业务需求,那么这个时候往往就需要我们自己自定义一个dialog
下面将直接给出我封装的一个dialog demo,用户可以自定义头部区域、内容区域以及底部的工具栏区域
customDialog.vue
<template>
<div v-if="showDialog">
<transition name="fade" appear>
<div class="modal-overlay"></div>
</transition>
<transition name="pop" appear>
<div class="modal" role="dialog" :style="{ width: `${width}px` }">
<!-- 头部标题区域 -->
<slot name="title"></slot>
<div class="model-title" v-if="!$slots.title">
<div class="title-text">
<span class="main-title">{{ title }}</span>
<div class="icon-close" v-if="showClose">
<i class="el-icon-close main-text" @click="close"></i>
</div>
</div>
<div class="semiel-lipse" v-show="isShowSemielLipse"></div>
</div>
<!-- 主体内容区域 -->
<div class="model-body">
<slot></slot>
</div>
<!-- 操作按钮区域 -->
<slot name="buttons"></slot>
<!-- 默认按钮 -->
<div class="footer_btn" v-if="!$slots.buttons">
<!-- 确认按钮 -->
<div class="dis_in_center" v-if="showConfimButton">
<el-button
:disabled="disabled"
:type="confimBtnType"
:loading="confimBtnLoading"
:size="size"
@click="confim"
>
{{ confimText }}
</el-button>
</div>
<!-- 取消按钮 -->
<div
class="dis_in_center right-btn"
v-if="showCancelButton"
:class="{ margin_left_20: showCancelButton }"
>
<el-button plain :type="cancelType" :size="size" @click="close">
{{ cancelText }}
</el-button>
</div>
</div>
</div>
</transition>
</div>
</template>
<script>
export default {
name: "CustomDialog",
components: {},
model: {
prop: "showDialog",
event: "change",
},
props: {
// 是否显示头部区域的自定义样式
isShowSemielLipse: {
type: Boolean,
default: false,
},
// 弹框的显示隐藏
showDialog: {
type: Boolean,
default: false,
},
// 底部按钮大小
size: {
type: String,
default: "medium",
},
// 宽度设置
width: {
type: [String, Number],
default: "600",
},
// 是否显示右上角的关闭按钮
showClose: {
type: Boolean,
default: true,
},
// 弹框标题
title: {
type: String,
default: "标题",
},
// 确认按钮
confimText: {
type: String,
default: "保存",
},
// 确认按钮loading
confimBtnLoading: {
type: Boolean,
default: false,
},
// 是否显示确认按钮
showConfimButton: {
type: Boolean,
default: true,
},
// 是否显示取消按钮
showCancelButton: {
type: Boolean,
default: true,
},
// 是否禁用确认按钮
disabled: {
type: Boolean,
default: false,
},
// 确认按钮类型
confimBtnType: {
type: String,
default: "primary",
},
// 取消按钮类型
cancelType: {
type: String,
default: "info",
},
// 取消按钮文本
cancelText: {
type: String,
default: "取消",
},
// 关闭按钮前的事件处理
beforeClose: {
type: Function,
default: () => {
return true;
},
},
},
methods: {
// 点击了关闭按钮/取消按钮
close() {
const data = this.beforeClose();
if (!data) return;
this.$emit("change", false);
},
// 点击了确认按钮
confim() {
this.$emit("confim", false);
},
},
};
</script>
<style scoped>
.main-title {
font-weight: 700;
color: #111218;
font-size: 16px;
}
.main-text {
color: #111218;
}
.modal {
position: absolute;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
height: fit-content;
/* box-shadow: 0px 5px 15px 0px rgba(255, 102, 0, 0.3); */
box-shadow: 0px 5px 15px 0px rgba(255, 255, 255, 0.3);
min-width: 400px;
border-radius: 1rem;
overflow: hidden;
background: #fff;
z-index: 999;
border-radius: 4px;
transform: none;
}
.model-body {
padding: 2rem;
min-height: 2rem;
max-height: 70vh;
overflow-y: auto;
}
.model-title {
position: relative;
height: 64px;
text-align: center;
overflow: hidden;
line-height: 64px;
width: 100%;
color: #fff;
font-size: 18px;
/* box-shadow: 0 -4px 12px rgba(0,0,0,.15)!important; */
}
.semiel-lipse {
position: absolute;
width: 110%;
left: -5%;
height: 150%;
top: -50%;
background: rgba(255, 102, 0, 0.8);
border-radius: 0% 0% 50% 50%;
}
.title-text {
position: relative;
z-index: 1000;
}
.icon-close {
position: absolute;
right: 42px;
top: 0;
line-height: 44px;
}
.icon-close i {
cursor: pointer;
}
.modal-overlay {
content: "";
position: absolute;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 998;
background: rgba(0, 0, 0, 0.4);
}
.footer_btn {
text-align: center;
padding-bottom: 20px;
padding-top: 20px;
border-top: 1px solid #f5f5f5;
}
.dis_in_center {
display: inline-block;
vertical-align: middle;
}
.right-btn {
margin-left: 20px;
}
/* 动画 */
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.4s linear;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
.pop-enter-active,
.pop-leave-active {
transition: transform 0.4s cubic-bezier(0.5, 0, 0.5, 1), opacity 0.4s linear;
}
.pop-enter,
.pop-leave-to {
opacity: 0;
transform: scale(0.3) translateY(-50%);
}
</style>
使用方式:
<template>
<div>
<custom-dialog
v-model="showDialog"
width="1200"
confimText="确认"
cancelType="primary"
:confimBtnLoading="confimBtnLoading"
@confim="confirmModel"
@change="changeModel"
title="选择部门"
>
<!-- 自定义标题 -->
<template #title>
<div class="custom-dialog-title">
<span style="font-size: 30px; font-weight: bold; color: #000000">
xxxxxx
</span>
</div>
<!-- 自定义内容 -->
<div>....</div>
<!-- 自定义按钮 -->
<template #buttons>
<div>
...
</div>
</template>
</template>
</custom-dialog>
</div>
</template>
import customDialog from "../components/CustomDialog.vue";
export default {
components: {
customDialog
}
}
效果: