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) {}
                    }
                });
            }
        }
    }
}

 

原文地址:http://www.cnblogs.com/mmdt/p/16921955.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性