小程序中的滚动穿透


在小程序开发中,弹出层滚动穿透是个比较棘手的问题。如下图,蓝色部分滚动,底部也跟着一起滚动,就是滚动穿透。

常见的处理方法比如,禁止滚动,并不生效。而给主体加 overflow: hidden 又会导致主体滚动条高度为 0,需要关闭时候记录滚动条位置,体验也不好。

touch-action

描述
auto 启用
none 禁用
pan-x 启用单指水平移动
pan-y 启用垂直手势
manipulation 浏览器只允许进行滚动和持续缩放操作。任何其它被auto值支持的行为不被支持。启用平移和缩小缩放手势,但禁用其他非标准手势,例如双击以进行缩放。 禁用双击可缩放功能可减少浏览器在用户点击屏幕时延迟生成点击事件的需要。
pinch-zoom 启用多手指平移和缩放页面
pan-left, pan-right,pan-up,pan-down 启用指定方向滚动开始的单指手势

在 mask 和 popup 元素上面禁用即可:

.mask, .popup {
    touch-action: none
}

这里和 overflow 方式类似,都不是特别好的办法,能解决部分问题,但是不完美。

注意:这里适合 popup 内部没有滚动的情况

禁止冒泡和默认行为

preventDefault:阻止默认滚动动作的执行。
stopPropagation: 阻止冒泡,阻止事件由下向上传递。

实现上,小程序这里需要借助 sjs 的能力来实现:
sjs 文件:

<!-- sjs 文件 -->
function disableScroll(e){
  e.preventDefault()
}

function enableScroll(e){
// 阻止冒泡
  e.stopPropagation()
}

export default {
  disableScroll,
  enableScroll
}

axml文件:

<import-sjs from="./index.sjs" name="sjs" />

<view class="wrapper" >
  <view a:for="{{[1, 2, 3, 4, 5, 6, 7, 8, 9]}}" a:for-item="i">
    <view class="item">{{i}}</view>
  </view>

  <view onTouchMove="{{sjs.disableScroll}}">
    <view class="mask" />

    <view class="popup" >
      <scroll-view scroll-y class="popup-scroll" onTouchMove="{{sjs.enableScroll}}">
        <view a:for="{{[1, 2, 3, 4, 5, 6, 7, 8, 9]}}" a:for-item="i">
          <view class="item2">{{i}}</view>
        </view>
      </scroll-view>
    </view>
  </view>
</view>

或者,我们把阻止默认事件放到 mask 层上面,那么下面的 scroll-veiw 不处理,也能够正常滚动

<import-sjs from="./index.sjs" name="sjs" />
<view class="wrapper" >
  <view a:for="{{[1, 2, 3, 4, 5, 6, 7, 8, 9]}}" a:for-item="i">
    <view class="item">{{i}}</view>
  </view>

  <view >
    <view class="mask" onTouchMove="{{sjs.disableScroll}}" />
    <view class="popup" >
      <scroll-view scroll-y class="popup-scroll" >
        <view a:for="{{[1, 2, 3, 4, 5, 6, 7, 8, 9]}}" a:for-item="i">
          <view class="item2">{{i}}</view>
        </view>
      </scroll-view>
    </view>
  </view>
</view>

 上一篇
umami 源码分析 umami 源码分析
umami 不使用 cookie 、localstorage 实现了 uv 识别,符合最新的隐私规范,代码也比较精简。花了一点时间,研究了这部分的实现,还是很有意思的。 技术框架:next.js + mysql/postgresql整体看下
2022-06-26
下一篇 
H5-dooring 后端常见问题 H5-dooring 后端常见问题
H5-dooring 后端是 koa2,数据库是直接读写的本地json文件,没有sql,没有redis。我们上线之后,一直有各种各样的问题,简单梳理下,不涉及具体代码,不涉及业务细节。 pm2 频繁重启日志文件是直接读写,没有按照时间分割,
2022-01-23
  目录