弹窗B滑动,禁止下层A scroll滚动

当弹窗B滑动时,下层元素A的滚动无法被阻止,即使使用了event.stopPropagation()和event.preventDefault()。分析发现这可能是浏览器行为,当body高度超过100vh时会出现该现象。解决方案是限制body高度不超过100vh,避免出现滚动条,从而阻止下层元素滚动。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题:

不管如何禁止(event.stopPropagation();event.preventDefault()),阻止默认事件,中断消息传播,都不行。

代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        .scrollbox{
            width: 100%;
            //height: 100vh;//----------------------------------->这里是关键
            background-color: aquamarine;
            overflow: scroll;
        }
        .scroll{
            position: absolute;
            top: 100px;
            width: 100%;
            height: 400px;
            background-color: beige;
            overflow: scroll;
        }
        .neirong{
            height: 700px;
            background-color:coral;
        }
    </style>
    
</head>
<body>
    <div class="scrollbox">
            3<br>
            1<br>
            1<br>
            1<br>
            1<br>
            1<br>
            1<br>
            6<br>
            1<br>
            1<br>
            1<br>
            1<br>
            1<br>
            1<br>
            2<br>3<br>
            1<br>
            1<br>
            1<br>
            1<br>
            1<br>
            1<br>
            6<br>
            1<br>
            1<br>
            1<br>
            1<br>
            1<br>
            1<br>
            2<br>3<br>
            1<br>
            1<br>
            1<br>
            1<br>
            1<br>
            1<br>
            6<br>
            1<br>
            1<br>
            1<br>
            1<br>
            1<br>
            1<br>
            2<br>
        
    </div>
    <div class="scroll">
            <div class="neirong">
                3<br>
                1<br>
                1<br>
                1<br>
                1<br>
                1<br>
                1<br>
                6<br>
                1<br>
                1<br>
                1<br>
                1<br>
                1<br>
                1<br>
                2<br>
            </div>
    </div>
</body>
<script>
        let scrolldiv = document.querySelector('.scroll');
        scrolldiv.addEventListener('touchstart',function(event){
            console.log(this,event)
            // event.stopPropagation();
        },
        false
        )
        let scrollbox = document.querySelector('.scrollbox');
        scrollbox.addEventListener('touchstart',function(event){
            console.log('body-------------',this,event,)
            // event.preventDefault()
            // event.stopPropagation();
        }
        // ,{ passive: false}
        )
    </script>
</html>

效果:

橙色区域,滑动到底部和顶部,再继续滑动,就会带动绿色滑动。

而console.log('body-------------',this,event)没有答应,说明 绿色的块 滚动,跟事件阻止和中断消息传播没有关系。

猜测这是浏览器的行为;只要body高度超过100vh,这种行为就会出现。

解决办法:

不让body高度超过100vh,既不然body出现滚动条。

.scrollbox{
            height: 100vh;//body不会出现滚动条

}

<think>好的,我现在需要在UniApp中实现一个弹窗打开时禁止底层页面滚动的功能。用户提到了滚动穿透的问题,也就是当弹窗内容滚动到底部后,继续滑动会导致底层页面跟着滚动,这确实会影响用户体验。我需要根据提供的引用资料,找到有效的解决方案。 首先,我应该回顾一下用户提供的引用内容。引用[1]和[2]都提到了滚动穿透的问题,并给出了两种方法。引用[5]中的方案二提到用CSS类来控制底层元素的样式,当弹窗显示时,给底层元素添加一个类,设置overflow: hidden和position: fixed,这样可以防止滚动。这种方法看起来比较直接,但可能会影响页面布局,因为设置position: fixed会导致页面跳回顶部吗? 然后,引用[4]中提到将弹窗内容使用scroll-view组件,这样可以在弹窗内部实现滚动,同时阻止底层滚动。这可能是一个可行的方案,但需要确保弹窗内的内容确实在scroll-view中,并且正确设置scroll-y属性。 另外,引用[3]提到原生组件的问题,但这里的问题可能不涉及原生组件,所以暂时可以忽略。引用[5]的方案一可能被用户省略了,但方案二已经提供了CSS的方法。 综合这些信息,可能的解决方案有两种:一种是使用CSS控制底层页面的overflow和定位,另一种是使用scroll-view组件来封装弹窗内容。我需要详细说明这两种方法的实现步骤,以及它们的优缺点。 首先,对于CSS方法,当弹窗显示时,给底层容器添加一个类,比如.tl-show,该类设置overflow: hidden、position: fixed、height和width为100%。这样可以防止底层页面滚动。需要注意的是,这样做可能会导致页面位置跳转,因为position: fixed会脱离文档流,可能让页面回到顶部。因此,在关闭弹窗时需要移除这个类,恢复原来的样式。 第二种方法是使用scroll-view。将弹窗的内容包裹在scroll-view组件中,并设置scroll-y属性允许垂直滚动。这样,当弹窗内部的scroll-view滚动到底部时,不会触发外层页面的滚动。同时,需要确保弹窗外的页面内容在弹窗显示时无法滚动,可能需要结合CSS方法,或者在弹窗出现时动态设置页面的overflow。 另外,引用[4]中的用户提到将B列表改为scroll-view解决了问题,这说明在弹窗内部使用scroll-view可以限制滚动范围,避免穿透到底层。因此,可能的最佳实践是同时使用CSS控制底层页面和scroll-view处理弹窗内容。 还需要注意,在UniApp中,页面结构可能涉及多个组件,需要正确找到底层页面的容器元素,通常是页面最外层的view。添加类名到该元素上,通过数据绑定控制类的存在与否,比如使用:class绑定mask变量,当弹窗显示时mask为true,触发.tl-show的样式。 最后,测试这两种方法,确保在弹窗打开时底层页面确实无法滚动,关闭弹窗后恢复滚动。同时,检查是否有布局错乱的问题,比如position: fixed导致的页面跳动,可能需要记录滚动位置并在关闭时恢复,但这样会增加复杂度。因此,可能优先推荐使用scroll-view结合overflow: hidden的方法,或者在不需要保持底层位置的情况下使用CSS方法。 总结步骤: 1. 使用CSS类动态控制底层容器,阻止滚动。 2. 弹窗内容使用scroll-view处理内部滚动。 3. 在打开弹窗时添加类,关闭时移除。</think>在UniApp中实现弹窗开启时禁用底层页面滚动,可通过以下两种主流方案解决滚动穿透问题: --- ### **方案一:CSS动态控制页面容器** 通过动态添加CSS类控制底层页面容器样式,适用于标准页面结构 **实现步骤**: 1. **页面结构改造** 在页面最外层容器添加动态类绑定: ```html <view :class="showPopup ? 'page-lock' : ''"> <!-- 页面主体内容 --> </view> <view v-if="showPopup" class="popup"> <!-- 弹窗内容 --> </view> ``` 2. **CSS样式定义** ```css .page-lock { overflow: hidden; /* 禁用滚动条 */ position: fixed; /* 脱离文档流 */ height: 100%; /* 保持容器高度 */ width: 100%; } ``` 3. **逻辑控制** ```javascript data() { return { showPopup: false } } ``` **优点**:实现简单,代码量少 **缺点**:页面会因`position: fixed`失去原有滚动位置[^5] --- ### **方案二:scroll-view封装弹窗内容** 通过滚动容器隔离滚动事件,适用于需要保留底层页面位置的场景 **实现步骤**: 1. **弹窗内容使用scroll-view** ```html <view v-if="showPopup" class="popup-mask"> <scroll-view scroll-y class="popup-content"> <!-- 可滚动内容 --> </scroll-view> </view> ``` 2. **CSS关键样式** ```css .popup-mask { position: fixed; top: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); } .popup-content { height: 70vh; /* 控制弹窗高度 */ } ``` 3. **阻止事件冒泡** 在遮罩层添加`@touchmove.stop`阻止触摸事件传递: ```html <view v-if="showPopup" class="popup-mask" @touchmove.stop> <!-- scroll-view内容 --> </view> ``` **优点**:保留底层页面滚动位置 **缺点**:需手动控制弹窗内容高度[^4] --- ### **终极增强方案** 结合两种方法实现最佳效果: 1. 使用`scroll-view`封装弹窗内容 2. 通过动态类禁用页面滚动 3. 添加以下代码保留页面位置: ```javascript methods: { openPopup() { this.scrollTop = document.documentElement.scrollTop; this.showPopup = true; }, closePopup() { this.showPopup = false; uni.pageScrollTo({ scrollTop: this.scrollTop }); } } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值