# 弹框组件的实现
# 需求分析
- 需要一个 参数 去控制弹框的显示
- 显示出的画面是多层文本对象堆叠出的结果,它需要有 父级元素 , 遮布 , 中心图块 ,三个文本对象合成展示。
- 需要一个按钮去 控制关闭
- 同时兼容PC端,移动端
# 基本实现
# 模板代码
// 父级元素
<template>
<div class="popup" v-show="innerShow">
<div class="mark"></div>
<div class="popup-main" v-show="innerShow">
<!-- ...自定义添加内容 -->
<!-- 关闭按钮,script引入图片CloseImg -->
<div class="close common" :style="{ 'background': `url(${CloseImg})` }" @click.stop="handleClose"
@touchstart.stop="handleClose"></div>
</div>
</div>
</template>
# 添加Transition层
<!-- 给父级元素和主体元素添加Transition -->
<template>
<!-- 父级transition -->
<Transition name="container" :duration="500">
<div class="popup" v-show="innerIsShow">
<div class="popup-mark"></div>
<!-- 主题内容transition -->
<Transition name="main">
<div class="popup-main" v-show="innerIsShow">
<!-- 关闭按钮 -->
<div class="close common" :style="{ 'background': `url(${CloseImg})` }" @click.stop="handleClose"
@touchstart.stop="handleClose"></div>
</div>
</Transition>
</div>
</Transition>
</template>
# css代码
<style lang="scss" scoped>
.main-enter-from {
opacity: 0;
transform: scale(0);
}
.main-enter-to {
opacity: 1;
transition: all 0.5s ease;
}
.main-leave-from {
opacity: 1;
}
.main-leave-to {
opacity: 0;
transform: scale(0);
transition: all 1s ease;
}
.popup {
position: fixed;
top: 0;
right: 0;
width: 100%;
height: 100%;
// 内容层 z-index要比遮罩大,否则会被遮盖
.popup-mark {
position: absolute;
top: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, .6);
}
.popup-main {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
flex-direction: column;
.common {
background-repeat: no-repeat !important;
background-size: cover !important;
}
.close {
z-index: 999;
width: 35px;
height: 35px;
margin-top: 30px;
}
}
}
</style>
# script代码
<script>
/**
* 弹窗组件
* @emit {boolean} setClose参数值 用于设置props.isShow关闭
* @param {boolean} isShow 是否显示勋章
*/
import CloseImg from "./img/close.png";
export default {
data() {
return {
CloseImg, // 关闭图片
innerIsShow: this.isShow, // 接收父级的isShow
}
},
methods: {
handleClose() {
// 关闭父组件传进来的isShow
this.$emit("setClose", false);
this.innerIsShow = false;
},
},
props: {
isShow: {
type: Boolean,
required: true,
default: false,
},
},
watch: {
isShow(n) {
n == true && (this.innerIsShow = n);
},
}
}
</script>
# 添加动画
.main-enter-active {
animation: bounce-in 0.5s;
}
.main-leave-active {
animation: bounce-in 0.5s reverse;
}
@keyframes bounce-in {
0% {
transform: scale(0);
}
50% {
transform: scale(1.25);
}
100% {
transform: scale(1);
}
}
# 思路小结
- 模板结构分为三部分: 父元素、 遮布、 中间图块
- 图层优先级(
z-index
: 中间图块 > 遮布 > 父元素 - 图块居中方案选择
flex
(justify-content:center;align-items:center
)布局。最开始借鉴他人的 父相子绝 (top:50%; left:50%; transform: translate(-50%,-50%))
,但考虑中间图块还需要添加 自定义内容,因此后者方案不考虑。 - 简单的弹出
bounce
特效,是通过transform: scale(x)
和 动画的enter
、leave
实现的。 props
接收到的数据并不是响应式的,需要本地data
自己创建一个字段。