<template> <view v-if="showSelf" class="dialog" :style="{'z-index': zIndex}"> <view class="dialog-mark" @click.self="closeMyself" :style="{'z-index': zIndex + 1}" @click="cancel"></view> <transition name="dialog"> <view class="dialog-sprite" :style="{'z-index': zIndex + 2}"> <!-- 标题 --> <section v-if="title" class="header"> <!-- 标题 --> <view class='titleT'>{{ title }}</view> <view class='titleI' @click="cancel"></view> </section> <!-- 弹窗的主题内容 --> <section class="dialog-body"> <slot></slot> </section> </view> </transition> </view> </template> <script> export default { name:"modal", props: { //弹窗组件是否显示 默认不显示 必传属性 show: { type: Boolean, default: false, required: true, }, title: { type: String, required: true, }, showCancel: { typs: Boolean, default: false, required: false, }, cancelText: { type: String, default: '取消', required: false, }, confirmText: { type: String, default: '确定', required: false, }, }, data() { return { name: 'dialog', showSelf: false, zIndex: this.getZIndex(), bodyOverflow: '' }; }, watch: { show(val) { if (!val) { this.closeMyself() } else { this.showSelf = val } } }, created() { this.showSelf = this.show; }, mounted() { // this.forbidScroll() }, methods:{ /** 禁止页面滚动 */ // forbidScroll() { // this.bodyOverflow = document.body.style.overflow // document.body.style.overflow = 'hidden' // }, /** 每次获取之后 zindex 自动增加 */ getZIndex() { let zIndexInit = 20190315; return zIndexInit++ }, /** 取消按钮操作 */ cancel() { this.$emit('cancel', false); }, /** 确认按钮操作 */ confirm() { this.$emit('confirm', false) }, /** 点击遮罩关闭弹窗 */ closeMyself(event) { this.showSelf = false; // this.sloveBodyOverflow() }, /** 恢复页面的滚动 */ // sloveBodyOverflow() { // document.body.style.overflow = this.bodyOverflow; // }, } } </script> <style> // 弹窗动画 // 弹窗动画 .dialog-enter-active, .dialog-leave-active { transition: opacity .5s; } .dialog-enter, .dialog-leave-to { opacity: 0.5; } .dialog { position: fixed; top: 0; right: 0; width: 100%; height: 100%; } // 内容层 z-index要比遮罩大,否则会被遮盖 .dialog-mark { position: absolute; top: 0; height: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, .6); } .dialog-sprite { // 移动端使用felx布局 position: absolute; left: 0%; right: 0%; bottom: 0%; display: flex; flex-direction: column; height: 60%; min-height: 180rpx; overflow: hidden; z-index: 23456765435; background: #fff; } .header { display: flex; height: 120rpx; font-size: 32rpx; font-family: PingFangSC-Medium, PingFang SC; font-weight: 500; color: #1E1E1E; line-height: 45rpx; text-align: center; border-bottom:1rpx solid #F2F2F2; } .titleT{ flex: 1; margin-right:190rpx; height: 50rpx; font-size: 36rpx; font-family: PingFangSC-Regular, PingFang SC; font-weight: 400; color: #757575; line-height: 120rpx; text-align: right; vertical-align: middle; } .titleI{ margin-top: 30rpx; margin-right: 32rpx; width: 48rpx; height: 48rpx; background:url('https://ddh.yyhock.com/appStatic/modal-icon.png') no-repeat; background-size: 100%; vertical-align: middle; } .dialog-body { flex: 1; overflow-x: hidden; overflow-y: scroll; } .dialog-footer { position: relative; display: flex; width: 100%; } &::after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 1rpx; background: #ddd; transform: scaleY(.5); } .btn { flex: 1; text-align: center; padding: 15rpx; font-size: 17rpx; } &:nth-child(2) { position: relative; } &::after { content: ''; position: absolute; left: 0; top: 0; width: 1rpx; height: 100%; background: #ddd; transform: scaleX(.5); } .btn-confirm { color: #43ac43; } </style>