vue之封装一个 弹窗组件 dialog
- 实现效果:
- 点击按钮,弹窗显示出来
- 点击关闭 || 取消 || 确定 弹窗隐藏
- 弹出时候带着遮罩层以及过渡动画效果
- 关闭时候,可以点击遮罩层关闭,
- mashFlag熟悉控制是否点击遮罩层 是否触发关闭弹窗事件
<template>
<!-- 遮罩层 self只是点击自己-->
<transition name="dialog-fade">
<div class="dialog_wrap" v-show="visible" @click.self="handleMaskClose">
<div class="dialog" :style="{ width, marginTop: top }">
<div class="dialog_header">
<!-- 标题的具名插槽 不传值时候 直接取title 否者替换slot-->
<slot name="title">
<span class="dialog_header_title">{{ title }}</span>
</slot>
<button class="dialog_header_btn" @click="handleClose">
<span class="removes" titl="关闭"></span>
</button>
</div>
<div class="dialog_body">
<slot>
<span>这是一条消息</span>
</slot>
</div>
<div class="dialog_footer">
<slot name="footer"></slot>
<slot name="footer">
<button class="dialog_footer_cancel" @click="handleCancel">
取消
</button>
<button class="dialog_footer_comfirm" @click="handleComfirm">
确定
</button>
</slot>
</div>
</div>
</div>
</transition>
</template>
<script>
export default {
name: "Dialog",
props: {
title: {
type: String,
default: "消息",
},
width: {
type: String,
default: "50%",
},
top: {
type: String,
default: "15vh",
},
visible: {
type: Boolean,
default: false,
},
mashFlag: {
type: Boolean,
default: true,
},
},
data() {
return {};
},
methods: {
handleMaskClose() {
if (!this.mashFlag) return false;
this.$emit("update:visible", false);
},
handleClose() {
this.$emit("update:visible", false);
},
handleCancel() {
this.$emit("handleCancel");
},
handleComfirm() {
this.$emit("handleComfirm");
},
},
components: {},
};
</script>
<style lang="scss" scoped>
.dialog-fade-enter-active {
animation: fade 0.5s;
}
.dialog-fade-leave-active {
animation: fade 0.5s reverse;
}
@keyframes fade {
0% {
opacity: 0;
transform: translateY(-20px);
}
100% {
opacity: 1;
transform: translateY(0px);
}
}
.dialog_wrap {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: auto;
margin: 0;
z-index: 2001;
background: rgba(0, 0, 0, 0.5);
.dialog {
position: relative;
margin: 15vh auto 50px;
background: #fff;
border-radius: 2px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
box-sizing: border-box;
width: 30%;
& > .dialog_header {
padding: 20px 20px 10px;
line-height: 24px;
font-size: 18px;
color: #303133;
.dialog_header_btn {
position: absolute;
top: 20px;
right: 20px;
padding: 0;
background: transparent;
border: none;
outline: none;
cursor: pointer;
font-size: 16px;
}
.removes {
position: absolute;
right: 0;
top: 0;
color: #303133;
cursor: pointer;
}
.removes::before {
content: "\2716";
}
}
& > .dialog_body {
padding: 30px 20px;
color: #606266;
font-size: 14px;
word-break: break-all;
}
& > .dialog_footer {
padding: 10px 20px 20px;
text-align: right;
box-sizing: border-box;
button {
background: transparent;
padding: 4px 6px;
border: none;
outline: none;
cursor: pointer;
font-size: 14px;
border: 1px solid #ccc;
}
.dialog_footer_cancel {
margin-right: 20px;
}
}
}
}
</style>
使用dialog组件 Home.vue
<template>
<div class="home">
<!-- <Dialog title="消息弹窗" width="60%" top="200px">
<div slot="title">我是弹窗</div>
</Dialog> -->
<!-- @close="close" -->
<Dialog :visible.sync="visible" @handleCancel="cancel" @handleComfirm="comfirm">
<div>我是body</div>
<!-- 若是替换底部按钮 使用以下方式 -->
<!-- <div slot="footer">
<button class="dialog_footer_cancel" @click="cancel">取消</button>
<button class="dialog_footer_comfirm" @click="comfirm">确定</button>
</div> -->
</Dialog>
<button @click="btnShow">点击显示</button>
<!-- transition包裹一个元素后,这个元素的显示和隐藏就会自动添加一些类名 -->
<transition name="dialog">
<div v-show="visible">我是动画</div>
</transition>
</div>
</template>
<script>
import Dialog from "./Test/dialog/Dialog.vue";
export default {
name: "Home",
components: {
Dialog,
},
data() {
return {
visible: false,
};
},
methods: {
btnShow() {
this.visible = true;
},
cancel() {
this.visible = false;
},
comfirm() {
this.visible = false;
},
},
};
</script>
<style lang="scss" scoped>
.home {
height: calc(100% - 34px);
width: calc(100% - 34px);
background: #fff;
padding: 16px;
border: 1px solid #ccc;
}
</style>