uni-app 官方组件uni-popup在支付宝小程序中弹出层出现滚动穿透问题

uni-app 官方组件uni-popup在支付宝小程序中弹出层出现滚动穿透问题

产品分类

uniapp/小程序/阿里

PC开发环境操作系统

Windows

PC开发环境操作系统版本号

Windows 10 专业版

HBuilderX类型

正式

HBuilderX版本号

3.6.18

第三方开发者工具版本号

3.8.11

基础库版本号

2.9.6

项目创建方式

HBuilderX

示例代码:

<template>  
    <view class="container" style="height: 150vh;">  
        <uni-card is-full :is-shadow="false">  
            <text class="uni-h6">弹出层组件用于弹出一个覆盖到页面上的内容,使用场景如:底部弹出分享弹窗、页面插屏广告等。</text>  
        </uni-card>  
        <uni-section title="基本示例" type="line">  
            <view class="example-body box">  
                <button class="button" type="primary" @click="toggle('top')">顶部</button>  
                <button class="button" type="primary" @click="toggle('bottom')">底部</button>  
                <button class="button" type="primary" @click="toggle('center')">居中</button>  
                <button class="button" type="primary" @click="toggle('left')">左侧</button>  
                <button class="button" type="primary" @click="toggle('right')">右侧</button>  
            </view>  
        </uni-section>  

        <uni-section title="提示消息" type="line">  
            <view class="example-body box">  
                <button class="button popup-success" @click="messageToggle('success')">成功</button>  
                <button class="button popup-error" @click="messageToggle('error')">失败</button>  
                <button class="button popup-warn" @click="messageToggle('warn')">警告</button>  
                <button class="button popup-info" @click="messageToggle('info')">信息</button>  
            </view>  
        </uni-section>  

        <uni-section title="对话框示例" type="line" class="hideOnPc">  
            <view class="example-body box">  
                <button class="button popup-success" @click="dialogToggle('success')">成功</button>  
                <button class="button popup-error" @click="dialogToggle('error')">失败</button>  
                <button class="button popup-warn" @click="dialogToggle('warn')">警告</button>  
                <button class="button popup-info" @click="dialogToggle('info')">信息</button>  
            </view>  
        </uni-section>  

        <uni-section title="输入框示例" type="line" padding>  
            <view class="dialog-box">  
                <text class="dialog-text">输入内容:{{ value }}</text>  
            </view>  
            <button class="button" type="primary" @click="inputDialogToggle">输入对话框</button>  

        </uni-section>  
        <uni-section title="底部分享示例" type="line" padding>  
            <button class="button" type="primary" @click="shareToggle">分享模版示例</button>  
        </uni-section>  
        <view>  
            <uni-popup ref="popup" background-color="#fff" @change="change">  
                <scroll-view scroll-y="true" style="height: 400rpx;">  
                        <view>测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试</view>  
                </scroll-view>  
            </uni-popup>  
        </view>  

        <view>  
            <uni-popup ref="message" type="message">  
                <uni-popup-message :type="msgType" :message="messageText" :duration="2000"></uni-popup-message>  
            </uni-popup>  
        </view>  

        <view>  
            <uni-popup ref="alertDialog" type="dialog">  
                <uni-popup-dialog :type="msgType" cancelText="关闭" confirmText="同意" title="通知" content="欢迎使用 uni-popup!" @confirm="dialogConfirm"  
                    @close="dialogClose"></uni-popup-dialog>  
            </uni-popup>  
        </view>  

        <view>  
            <uni-popup ref="inputDialog" type="dialog">  
                <uni-popup-dialog ref="inputClose"  mode="input" title="输入内容" value="对话框预置提示内容!"  
                    placeholder="请输入内容" @confirm="dialogInputConfirm"></uni-popup-dialog>  
            </uni-popup>  
        </view>  

        <view>  
            <uni-popup ref="share" type="share" safeArea backgroundColor="#fff">  
                <uni-popup-share></uni-popup-share>  
            </uni-popup>  
        </view>  
    </view>  
</template>  

<script>  
    export default {  
        data() {  
            return {  
                type: 'center',  
                msgType: 'success',  
                messageText: '这是一条成功提示',  
                value: ''  
            }  
        },  
        onReady() {},  
        methods: {  
            change(e) {  
                console.log('当前模式:' + e.type + ',状态:' + e.show);  
            },  
            toggle(type) {  
                this.type = type  
                this.$refs.popup.open(type)  
            },  
            messageToggle(type) {  
                this.msgType = type  
                this.messageText = `这是一条${type}消息提示`  
                this.$refs.message.open()  
            },  
            dialogToggle(type) {  
                this.msgType = type  
                this.$refs.alertDialog.open()  
            },  
            dialogConfirm() {  
                console.log('点击确认')  
                this.messageText = `点击确认了 ${this.msgType} 窗口`  
                this.$refs.message.open()  
            },  
            inputDialogToggle() {  
                this.$refs.inputDialog.open()  
            },  
            dialogClose() {  
                console.log('点击关闭')  
            },  
            dialogInputConfirm(val) {  
                uni.showLoading({  
                    title: '3秒后会关闭'  
                })  

                setTimeout(() => {  
                    uni.hideLoading()  
                    console.log(val)  
                    this.value = val  
                    this.$refs.inputDialog.close()  
                }, 3000)  
            },  
            shareToggle() {  
                this.$refs.share.open()  
            }  
        }  
    }  
</script>  
<style lang="scss">  
    @mixin flex {  
        display: flex;  
        flex-direction: row;  
    }  

    @mixin height {  
        height: 100%;  
        /* #ifdef APP-NVUE */  
        flex: 1;  
        /* #endif */  
    }  

    .box {  
        @include flex;  
    }  

    .button {  
        @include flex;  
        align-items: center;  
        justify-content: center;  
        flex: 1;  
        height: 35px;  
        margin: 0 5px;  
        border-radius: 5px;  
    }  

    .example-body {  
        background-color: #fff;  
        padding: 10px 0;  
    }  

    .button-text {  
        color: #fff;  
        font-size: 12px;  
    }  

    .popup-content {  
        @include flex;  
        align-items: center;  
        justify-content: center;  
        padding: 15px;  
        height: 50px;  
        background-color: #fff;  
    }  

    .popup-height {  
        @include height;  
        width: 200px;  
    }  

    .text {  
        font-size: 12px;  
        color: #333;  
    }  

    .popup-success {  
        color: #fff;  
        background-color: #e1f3d8;  
    }  

    .popup-warn {  
        color: #fff;  
        background-color: #faecd8;  
    }  

    .popup-error {  
        color: #fff;  
        background-color: #fde2e2;  
    }  

    .popup-info {  
        color: #fff;  
        background-color: #f2f6fc;  
    }  

    .success-text {  
        color: #09bb07;  
    }  

    .warn-text {  
        color: #e6a23c;  
    }  

    .error-text {  
        color: #f56c6c;  
    }  

    .info-text {  
        color: #909399;  
    }  

    .dialog,  
    .share {  
        display: flex;  
        flex-direction: column;  
    }  

    .dialog-box {  
        padding: 10px;  
    }  

    .dialog .button,  
    .share .button {  
        width: 100%;  
        margin: 0;  
        margin-top: 10px;  
        padding: 3px 0;  
        flex: 1;  
    }  

    .dialog-text {  
        font-size: 14px;  
        color: #333;  
    }  
</style>  

操作步骤:

示例代码运行到支付宝小程序中就可以复现 (需要真机测试 我用的安卓iqooz1 ios未测)

预期结果:

uni-popup 正常在弹出层滚动

实际结果:

uni-popup 弹出层后面的页面出现滚动

bug描述:

页面在Hello uni-app项目 pages/extUI/popup/popup.vue
复制上面代码到官方的 Hello uni-app 项目,运行到支付宝小程序中就可以复现 (要使用真机测试)
具体表现行为可以看附件视频
1cd7676cca6700c702d759d3633bbd1b.zip

5 回复

这好像是弹窗组件本身的问题。 文档中有关于穿透的解决办法。

这个不是BUG哦

这不是bug,由于平台自身原因,除了h5平台外 ,其他平台都不能在在组件内禁止滚动穿透,所以在微信小程序、App 平台,页面内需要用户特殊处理一下
,详见:处理滚动穿透

在支付宝小程序中使用 uni-popup 组件时,弹出层出现滚动穿透问题是一个常见问题。滚动穿透指的是当弹出层出现时,底层的页面仍然可以滚动,这会影响用户体验。以下是一些解决方案:

1. 使用 catchtouchmove 事件

在弹出层的根元素上添加 catchtouchmove 事件,可以阻止触摸事件的默认行为,从而防止滚动穿透。

<uni-popup ref="popup" @change="popupChange">
  <view class="popup-content" catchtouchmove="preventScroll">
    <!-- 弹出层内容 -->
  </view>
</uni-popup>
methods: {
  preventScroll() {
    // 阻止默认滚动行为
    return false;
  }
}

2. 动态设置页面的 overflow 样式

在弹出层显示时,动态设置页面的 overflow 样式为 hidden,隐藏时再恢复为 auto

methods: {
  popupChange(e) {
    if (e.show) {
      // 弹出层显示时,禁止页面滚动
      document.body.style.overflow = 'hidden';
    } else {
      // 弹出层隐藏时,恢复页面滚动
      document.body.style.overflow = 'auto';
    }
  }
}

3. 使用 position: fixed 锁定页面

在弹出层显示时,将页面的 position 设置为 fixed,隐藏时再恢复为 static

methods: {
  popupChange(e) {
    if (e.show) {
      // 弹出层显示时,锁定页面
      document.body.style.position = 'fixed';
      document.body.style.width = '100%';
    } else {
      // 弹出层隐藏时,恢复页面
      document.body.style.position = 'static';
    }
  }
}

4. 使用 scroll-view 包裹内容

如果弹出层内部有滚动需求,可以使用 scroll-view 包裹内容,并设置 scroll-y 属性。

<uni-popup ref="popup">
  <scroll-view scroll-y class="popup-content">
    <!-- 弹出层内容 -->
  </scroll-view>
</uni-popup>

5. 使用 uni-popupmask 属性

确保 uni-popupmask 属性设置为 true,这样在弹出层显示时会有一个遮罩层,可以阻止用户操作底层页面。

<uni-popup ref="popup" :mask="true">
  <view class="popup-content">
    <!-- 弹出层内容 -->
  </view>
</uni-popup>

6. 使用 uni-popupmask-click 属性

如果希望在点击遮罩层时关闭弹出层,可以设置 mask-click 属性为 true

<uni-popup ref="popup" :mask="true" :mask-click="true">
  <view class="popup-content">
    <!-- 弹出层内容 -->
  </view>
</uni-popup>

7. 使用 uni-popupsafe-area 属性

在弹出层显示时,确保内容不会超出安全区域,可以设置 safe-area 属性为 true

<uni-popup ref="popup" :safe-area="true">
  <view class="popup-content">
    <!-- 弹出层内容 -->
  </view>
</uni-popup>
回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!