效果并不完整,有需求可以自行修改
适用于vue2 弹窗只支持居中弹出和下方弹出,内容可以自定义
效果图
子组件
代码
新建组件文件夹 zPopup
<template>
<view class="zPopup_show" v-if="style_show"
:class="mode=='center'?(show?'zPopup_show_center openAnimation':'zPopup_show_center closeAnimation'):mode=='bottom'?(show?'zPopup_show_bottom openAnimation':'zPopup_show_bottom closeAnimation'):''"
@tap.stop="maskClose?colosePopue():()=>{}">
<view class="zSlotViews"
:class="mode=='bottom'?(show?'zSlotViews_bottom_open ':'zSlotViews_bottom_close '):''" @tap.stop="()=>{}">
<view class="zSlotView">
<image class="colseIcon" src="" mode="aspectFit" @tap.stop="colosePopue"></image>
<!-- 插槽内容可以自定义 -->
<slot name="center"></slot>
</view>
</view>
</view>
</template>
<script>
export default {
name: "zPopup",
//show 主要控制动画效果
//mode 设置方向弹出
// maskClose 是否可以通过 点击遮罩层来关闭 弹窗
props: ['show', 'mode', 'maskClose'],
//style_show 控制显示不显示
data() {
return {
style_show: null //控制显示不显示
};
},
onLoad() {
},
onShow() {
},
watch: {
show: {
handler(newName, oldName) {
// console.log(newName, '新值');
// console.log(oldName, '老值');
//为true是开启动画,动画效果不用延迟出现
//为false是关闭动画,动画效果先关闭 再进行整个弹窗的关闭,不会出现回显数据消失
if (newName) {
this.style_show = newName;
} else {
setTimeout(() => {
this.style_show = newName;
}, 300)
}
},
immediate: true,
deep: true
}
},
methods: {
//关闭弹窗
colosePopue() {
if (!this.style_show) {
return
}
this.$emit('closeCar')
}
}
}
</script>
<style lang="scss" scoped>
//居中显示
.zPopup_show_center {
width: 100vw;
height: 100vh;
position: fixed;
top: 0;
left: 0;
z-index: 999999999;
background: rgba(0, 0, 0, 0.6);
display: flex;
justify-content: center;
align-items: center;
opacity: 1;
border-radius: 0rpx !important;
}
.openAnimation {
animation: slow_show 0.22s linear;
}
.closeAnimation {
opacity: 0 !important;
animation: close_slow_show 0.22s linear;
}
@keyframes slow_show {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes close_slow_show {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
//从下方弹出显示
.zPopup_show_bottom {
width: 100vw;
height: 100vh;
position: fixed;
bottom: 0;
left: 0;
z-index: 999999999;
background: rgba(0, 0, 0, 0.6);
display: flex;
justify-content: center;
align-items: flex-end;
opacity: 1;
border-radius: 18rpx;
.zSlotViews {
width: 100% !important;
position: relative;
bottom: 0;
left: 0;
// padding: 30rpx 50rpx !important;
}
.zSlotViews_bottom_open {
animation: From_bottom_to_top 0.22s linear;
}
.zSlotViews_bottom_close {
animation: From_top_to_bottom 0.3s linear;
}
}
@keyframes From_bottom_to_top {
0% {
bottom: -100%;
}
100% {
bottom: 0;
}
}
@keyframes From_top_to_bottom {
0% {
bottom: 0;
}
100% {
bottom: -100%;
}
}
.zSlotViews {
width: 100vw !important;
box-sizing: border-box;
// background: #fff;
.zSlotView {
// background: #FFFFFF;
width: 100vw;
border-radius: 12rpx;
position: relative;
z-index: 10074;
display: flex;
justify-content: center;
align-items: center;
.colseIcon {
width: 40rpx;
height: 40rpx;
position: absolute;
right: 30rpx;
top: 30rpx;
background: lightcoral;
}
}
}
</style>
全局使用 挂载
//挂载悬浮窗
import zPopup from '@/components/zPopup/zPopup.vue'
Vue.component('zPopup ', zPopup )
单独使用
import zPopup from "@/components/zPopup /zPopup .vue"
components: {
zPopup
},
父组件使用
<template>
<view>
<view class="">
<zPopup :show="show" :mode="'center'" @closeCar="closeCar">
<!-- 插槽可自定义内容 -->
<template v-slot:center>
<view style="width: 100%;height: 500rpx;background: #fff;border-radius: 40rpx;"></view>
</template>
</zPopup>
</view>
<view class="" @tap="open()">
打开
</view>
</view>
</template>
js
<script>
import zPopup from "@/components/zPopup /zPopup .vue"
export default {
data() {
return {
show: false,
};
},
components: {
zPopup
},
methods: {
//打开弹窗
open() {
//做一些数据回显的话优先调接口,再显示弹窗
setTimeout(() => {
this.show = true;
}, 200)
},
//关闭弹窗
closeCar() {
this.show = false;
},
}
}
</script>
v3写法
子组件
<template>
<view class="zPopup_show" v-if="Data.style_show"
:class="mode=='center'?(show?'zPopup_show_center openAnimation':'zPopup_show_center closeAnimation'):mode=='bottom'?(show?'zPopup_show_bottom openAnimation':'zPopup_show_bottom closeAnimation'):''"
@tap.stop="maskClose?colosePopue():()=>{}">
<view class="zSlotViews"
:class="mode=='bottom'?(show?'zSlotViews_bottom_open ':'zSlotViews_bottom_close '):''" @tap.stop="()=>{}">
<view class="zSlotView">
<image class="colseIcon" src="" mode="aspectFit" @tap.stop="colosePopue"></image>
<!-- 插槽内容可以自定义 -->
<slot name="center"></slot>
</view>
</view>
</view>
</template>
<script setup>
import {
defineProps,
reactive,
watch,
defineEmits
} from "vue";
const props = defineProps({
show: {
default: false,
type: Boolean
},
mode: {
default: 'center',
type: String
},
maskClose: {
default: false,
type: Boolean
}
});
const Emits=defineEmits(['closeCar'])
const Data = reactive({
style_show: null //控制显示不显示
})
watch(() => props.show, (newv, oldv) => {
console.log(newv, '新值');
console.log(oldv, '老值');
if (newv) {
Data.style_show = newv;
} else {
setTimeout(() => {
Data.style_show = newv;
}, 300)
}
}, {
deep: true
})
const colosePopue = () => {
if (!Data.style_show) {
return
}
Emits('closeCar')
}
</script>
<style lang="scss" scoped>
//居中显示
.zPopup_show_center {
width: 100vw;
height: 100vh;
position: fixed;
top: 0;
left: 0;
z-index: 999999999;
background: rgba(0, 0, 0, 0.6);
display: flex;
justify-content: center;
align-items: center;
opacity: 1;
border-radius: 0rpx !important;
}
.openAnimation {
animation: slow_show 0.22s linear;
}
.closeAnimation {
opacity: 0 !important;
animation: close_slow_show 0.22s linear;
}
@keyframes slow_show {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes close_slow_show {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
//从下方弹出显示
.zPopup_show_bottom {
width: 100vw;
height: 100vh;
position: fixed;
bottom: 0;
left: 0;
z-index: 999999999;
background: rgba(0, 0, 0, 0.6);
display: flex;
justify-content: center;
align-items: flex-end;
opacity: 1;
border-radius: 18rpx;
.zSlotViews {
width: 100% !important;
position: relative;
bottom: 0;
left: 0;
// padding: 30rpx 50rpx !important;
}
.zSlotViews_bottom_open {
animation: From_bottom_to_top 0.22s linear;
}
.zSlotViews_bottom_close {
animation: From_top_to_bottom 0.3s linear;
}
}
@keyframes From_bottom_to_top {
0% {
bottom: -100%;
}
100% {
bottom: 0;
}
}
@keyframes From_top_to_bottom {
0% {
bottom: 0;
}
100% {
bottom: -100%;
}
}
.zSlotViews {
width: 100vw !important;
box-sizing: border-box;
// background: #fff;
.zSlotView {
// background: #FFFFFF;
width: 100vw;
border-radius: 12rpx;
position: relative;
z-index: 10074;
display: flex;
justify-content: center;
align-items: center;
.colseIcon {
width: 40rpx;
height: 40rpx;
position: absolute;
right: 30rpx;
top: 30rpx;
background: lightcoral;
}
}
}
</style>
父组件
<template>
<view class="content">
<template>
<view>
<view class="">
<zPopup :show="Data.show" :mode="'center'" @closeCar="closeCar">
<!-- 插槽可自定义内容 -->
<template v-slot:center>
<view style="width: 100%;height: 500rpx;background: #fff;border-radius: 40rpx;"></view>
</template>
</zPopup>
</view>
<view class="" @tap="open()">
打开
</view>
</view>
</template>
</view>
</template>
<script setup>
import zPopup from "@/components/zPopup/zPopup.vue"
import {
defineProps,
reactive,
watch
} from "vue";
const Data = reactive({
show: false //控制显示不显示
})
const open = () => {
//做一些数据回显的话优先调接口,再显示弹窗
console.log('触发了')
setTimeout(() => {
Data.show = true;
}, 200)
}
const closeCar = () => {
Data.show = false;
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 50rpx;
}
.text-area {
display: flex;
justify-content: center;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
</style>