uniapp中,在父组件(tabBar页面)关闭子组件(子组件包含uni-popup弹出层)的实现思路
uniapp项目开发中,关于使用uni-popup组件跨组件关闭打开的问题实现解决思路。
项目开发中,在tabBar页面引用了封装好的用来展示列表数据的子组件,该子组件中包含了uni-ui中的uni-popup弹出层组件。当popup弹出层打开时,切换tabBar页面的时候,popup并不会被关闭。期望的结果是:切换tabBar页面,popup关闭。
官网文档中,示例如下:
<template>
<view>
<button @click="open">打开弹窗</button>
<uni-popup ref="popup" type="bottom">底部弹出 Popup</uni-popup>
</view>
</template>
<script>
export default {
methods:{
open(){
// 通过组件定义的ref调用uni-popup方法 ,如果传入参数 ,type 属性将失效 ,仅支持 ['top','left','bottom','right','center']
this.$refs.popup.open('top')
}
}
}
</script>
项目中的代码(子组件):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) {} } }); } } } }

浙公网安备 33010602011771号