前言
在前面的工作中,已经确定好了页面的总体布局,现在来实现弹窗功能,用来介绍整个项目。
点击项目介绍按钮,出现弹窗,点击Done,关闭弹窗,具体效果如下:
弹窗的具体实现
弹窗功能的具体逻辑如下:
- 点击“项目介绍”按钮会触发 togglePopup 方法,该方法会切换 popupShow 的状态,从而控制弹窗的显示与隐藏。
togglePopup() {
this.popupShow = !this.popupShow; // 切换弹窗的显示状态
}
- 当 popupShow 状态为 true 时,弹窗组件会被渲染在页面上。弹窗组件包括了背景遮罩层和内容区域。在背景遮罩层上点击,或者点击弹窗中的“Done”按钮,会触发 closePopup 方法,关闭弹窗。
togglePopup() {
this.popupShow = !this.popupShow; // 切换弹窗的显示状态
}
模板部分
- title 属性绑定了弹窗的标题,可以通过父组件传递属性进行自定义。
- showDialog 属性控制弹窗的显示与隐藏,我们使用了双向绑定,即通过 v-model 将组件内部的 visible 属性与外部的 value 属性进行关联。
- width 属性控制弹窗的宽度,可以根据实际需求进行自定义。
- @close 事件绑定了 $emit(‘change’),当取消或者关闭按钮时触发,向父组件传递取消按钮被点击的信号。
- @confirm 事件绑定了 $emit(‘confirm’),当点击确认按钮时触发,向父组件传递确认按钮被点击的信号。
- showClose 是否显示右上角的关闭按钮。
插槽部分
- slot 标签用于显示弹窗的主要内容,父组件可以在使用标签时插入自定义的内容
属性部分
- showDialog 属性是组件的一个 props,用于控制弹窗的显示与隐藏,它的类型是布尔型,默认值为 false。
- confirmText 属性分别用于设置保存按的文本,默认值分别为 Done”。
- showConfirmButton属性用于设置保存按的显示和隐藏,默认值显示。
- confirmBtnType 和 cancelBtnType 属性分别用于设置保存按钮和取消按钮的类型,保存按钮默认值均为 primary,取消按钮默认值为 info。
- title 属性用于设置弹窗的标题,默认值为空字符串。
- width 属性用于设置弹窗的宽度,默认值为 “600px”。
- beforeClose 关闭按钮的事件处理。
<template>
<div v-if="showDialog" class="custom-dialog">
<div class="dialog-mask" @click="closeDialog"></div>
<div class="dialog-wrapper" :style="{ width: width }">
<div class="dialog-header">
<span>{{ title }}</span>
<button v-if="showClose" class="close-btn" @click="closeDialog">×</button>
</div>
<div class="dialog-body">
<slot></slot>
</div>
<div class="dialog-footer">
<button v-if="showCancelButton" @click="cancelDialog">{{ cancelText }}</button>
<button v-if="showConfirmButton" @click="confirmDialog">{{ confirmText }}</button>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'CustomDialog',
props: {
title: {
type: String,
default: ''
},
value: {
type: Boolean,
default: false
},
width: {
type: String,
default: '600px'
},
showClose: {
type: Boolean,
default: true
},
confirmText: {
type: String,
default: 'Done'
},
cancelText: {
type: String,
default: '取消'
},
showConfirmButton: {
type: Boolean,
default: true
},
showCancelButton: {
type: Boolean,
default: true
},
confirmBtnType: {
type: String,
default: 'primary'
},
cancelBtnType: {
type: String,
default: 'info'
},
beforeClose: Function
},
computed: {
showDialog: {
get() {
return this.value;
},
set(val) {
this.$emit('input', val);
}
}
},
methods: {
closeDialog() {
this.$emit('change', false);
this.showDialog = false;
},
cancelDialog() {
this.$emit('change', false);
this.showDialog = false;
},
confirmDialog() {
this.$emit('confirm');
this.showDialog = false;
}
}
};
</script>
<style scoped>
.custom-dialog {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
}
.dialog-mask {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
}
.dialog-wrapper {
background: #fff;
border-radius: 5px;
overflow: hidden;
z-index: 1000;
}
.dialog-header {
padding: 10px;
background: #f5f5f5;
border-bottom: 1px solid #ddd;
display: flex;
justify-content: space-between;
align-items: center;
}
.close-btn {
background: none;
border: none;
font-size: 20px;
}
.dialog-body {
padding: 20px;
}
.dialog-footer {
padding: 10px;
text-align: right;
background: #f5f5f5;
border-top: 1px solid #ddd;
}
</style>