uniapp项目开发中,关于使用uni-popup组件跨组件关闭打开的问题实现解决思路

        项目开发中,在tabBar页面引用了封装好的用来展示列表数据的子组件,该子组件中包含了uni-ui中的uni-popup弹出层组件。点击列表中的“立即兑换”按钮,此时popup弹出层打开,当切换tabBar页面的时候,popup并不会被关闭。期望的结果是:切换tabBar页面,popup关闭。如图:

        官网文档中,打开关闭popup是这样的:

        html:

<button @click="open">打开弹窗</button>
<uni-popup ref="popup" :mask-click="false">
	<text>Popup</text>
	<button @click="close">关闭</button>
</uni-popup>

        js:

export default {
	data() {
		return {}
	},
	onReady() {},
	methods: {
		open() {
			this.$refs.popup.open('top')
		},
		close() {
			this.$refs.popup.close()
		}
	}
}

        项目中的代码(子组件):handleToScratch函数中,将open与close传值给父组件,由父组件选择调用,如下:

<template>
	<view class="wrap">
		<view class="single" v-for="(item, index) in list" :key="index">
			<view class="mask"></view>
			<view class="mask2"></view>
			<view class="line"></view>
			<view class="content">
				<view class="first">
					<text>{{ item.score }}元</text>
				</view>
				<view class="second">
					<view class="second_title">
						<text>{{ item.scoreType | calScoreType }}</text>
					</view>
				</view>
				<view class="three" @click="handleToScratch(item)"></view>
			</view>
		</view>
		<!-- 普通弹窗 -->
		<uni-popup ref="popup">
			<view class="popup-content">
				<view><text class="title">请选择兑换期号</text></view>
				<uni-data-checkbox selectedColor="#FF6600" v-model="radio1" :localdata="selectList" @change="changeCheckbox"></uni-data-checkbox>
			</view>
		</uni-popup>
	</view>
</template>

<script>
export default {
	props: {
		list: {
			type: Array,
			default() {
				return [];
			}
		},
		selectList: {
			type: Array,
			default() {
				return [];
			}
		}
	},
	data() {
		return {
			radio1: '' //默认选择的号码
		};
	},
	filters: {
		calScoreType(newValue) {
			if (newValue === 1) {
				return 'xx兑换券';
			} else if (newValue === 2) {
				return 'xx兑换券';
			}
		}
	},
	watch: {
		radio1(val) {
			console.log(val, 'val');
		}
	},
	methods: {
		changeCheckbox(e) {
			if (e.detail.data.orderCount >= e.detail.data.maxOrderCount) {
				uni.showModal({
					content: '您选择的本期暂无余票,请选择其它日期的票!',
					showCancel: false
				});
				return;
			}
			if (Date.parse(new Date()) < Date.parse(e.detail.data.startSellTime)) {
				uni.showModal({
					content: '您选择的还没有到选号时间,请在每月8号进行选号!',
					showCancel: false
				});
				return;
			}
			if (Date.parse(new Date()) >= Date.parse(e.detail.data.endSellTime)) {
				uni.showModal({
					content: '您选择的已经截止选号,请在每月的8号选号!',
					showCancel: false
				});
				return;
			}
			this.$refs.popup.close();
			uni.navigateTo({
				url: `/subpages1/bet/bet?type=3&score=${e.detail.data.score}&issueNo=${e.detail.data.text}&issueId=${e.detail.value}&openingTime=${e.detail.data.openingTime}`
			});
			this.$nextTick(() => {
				this.radio1 = '';
			});
		},
		handleToScratch(item) {
			let _open = this.$refs.popup.open;
			let _close = this.$refs.popup.close;
			this.$emit('handleUp', item, _open, _close);
		}
	}
};
</script>

<style lang="scss" scoped>
.wrap {
	width: 100%;
	padding: 24rpx 24rpx;
	box-sizing: border-box;

	.single {
		width: 100%;
		height: 164rpx;
		background-color: #ff6600;
		border-radius: 20rpx;
		position: relative;
		overflow: hidden;
		margin-bottom: 20rpx;

		.mask {
			background-color: #f3f3f3;
			border-radius: 50%;
			width: 40rpx;
			height: 40rpx;
			position: absolute;
			left: 498rpx;
			top: -20rpx;
		}

		.mask2 {
			background-color: #f3f3f3;
			border-radius: 50%;
			width: 40rpx;
			height: 40rpx;
			position: absolute;
			left: 498rpx;
			bottom: -20rpx;
		}

		.line {
			width: 4rpx;
			height: 102rpx;
			background-color: #fff;
			position: absolute;
			left: 518rpx;
			top: 32rpx;
		}

		.content {
			width: 100%;
			height: inherit;
			box-sizing: border-box;
			padding: 0 32rpx 0 54rpx;
			display: flex;
			justify-content: space-between;

			.first {
				flex: 1;
				display: flex;
				justify-content: center;
				align-items: center;
				color: #ffffff;
				font-size: 38rpx;
				font-weight: bold;
			}

			.second {
				flex: 3;
				display: flex;
				padding-left: 30rpx;
				box-sizing: border-box;
				flex-direction: column;
				justify-content: center;
				align-items: flex-start;

				.second_title {
					font-size: 24rpx;
					color: #fff;
					margin-bottom: 14rpx;
				}

				.second_time {
					font-size: 20rpx;
					color: #fff;
				}
			}

			.three {
				background: url(../../static/personal_pic/exchange_button.png) no-repeat center / contain;
				flex: 1;
			}
		}
	}
	.popup-content {
		display: flex;
		flex-direction: column;
		justify-content: space-between;
		align-items: center;
		padding: 26rpx;
		height: auto;
		background-color: #fff;
		border-radius: 32rpx;

		.title {
			width: 100%;
			text-align: center;
			line-height: 70rpx;
			font-size: 30rpx;
		}
	}
}
</style>

        父组件(tabBar页面)中使用,本例中,父组件使用了mixins,下面代码中,handleUp方法由子组件触发,解决方法就是将popup的open与close存起来传递给父组件,由父组件在合适的时机调用

import {
	getHomeEquities,
	selectIssue
} from '@/request/api.js';
import {
	mapState
} from 'vuex';
export const getEquities = {
	data() {
		return {
			list: [],
			selectlist: [],
			_close: null
		};
	},
	computed: {
		...mapState('User', ['userId', 'phoneNumber'])
	},
	onLoad() {
		this.getHomeEquitiesData()
	},
	onHide() {
		this._close && this._close()
	},
	onPullDownRefresh() {
		this.getHomeEquitiesData()
		setTimeout(()=>{
			uni.stopPullDownRefresh()
		}, 1000)
	},
	methods: {
		getHomeEquitiesData() {
			uni.showLoading({
				title: '数据加载中...'
			})
			getHomeEquities(this.phoneNumber, this.userId)
				.then(res => {
					uni.hideLoading()
					if (res.data.code === 200) {
						if (res.data.data && res.data.data.length) {
							this.list = res.data.data;
						} else {
							uni.showToast({
								title: '暂无权益数据!',
								icon: 'none'
							});
						}
					} else if (res.data.code === 500) {
						uni.showToast({
							title: res.data.msg,
							icon: 'none'
						});
					}
				})
				.catch(err => {
					console.log(err);
				});
		},
		handleUp(item, _open, _close) {
			this._close = _close
			if (item.scoreType === 1) {
				_open('center');
				selectIssue(1).then(res => {
					if (res.data.code === 200) {
						this.selectlist = res.data.data.map(item2 => {
							return {
								text: item2.issueNo,
								value: item2.issueId,
								lotteryKind: item2.lotteryKind,
								lotteryKindId: item2.lotteryKindId,
								maxOrderCount: item2.maxOrderCount,
								orderCount: item2.orderCount,
								startSellTime: item2.startSellTime,
								endSellTime: item2.endSellTime,
								openingTime: item2.openingTime,
								score: item.score
							};
						});
					}
				});
			} else if (item.scoreType === 2) {
				uni.showModal({
					title: '提示',
					content: '确认订阅资讯月刊吗?',
					success: res => {
						if (res.confirm) {
							uni.navigateTo({
								url: '/pages/home/monthly/monthly'
							});
						} else if (res.cancel) {}
					}
				});
			}
		}
	}
}

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐