Skip to content

小程序滑动穿透问题的解决

一、场景

  • 在项目当中,基础遇到这样的需求

有一个长列表,或者其他可滚动展示的页面,
在这个页面会弹出一个Modal层,如下:

贝壳找房的 的筛选栏

二、问题

如果这个弹框内容不可滚动,不会有太大问题;

但是当弹出内容是可以滚动的时候,就会有问题,

触摸没有滚动的区域会发现滚动可以穿透,会传递给下面的列表页面,

三、解决方案

这里使用了Taro,但原理都是一样的。

思路解析

i、首先,需要在自定义弹框的根元素,添加 onTouchMove 监听,并阻止时间的冒泡

jsx
// 重点A:阻止事件冒泡
handleTouchMove = (e) => {
  e.stopPropagation()
}
<View className='rootClass' onTouchMove={this.handleTouchMove}>

ii、但是,里面的内容,就不能滚动了,那么,可以使用 ScrollView代替View,并开启Y轴的滚动

jsx

<!-- 重点B: ScrollView(开启scrollY)--> 
<ScrollView
        scrollY
        scrollX={false}
        className='layout-body__content'
    >
  <!-- 内容区域-->
  <!-- 内容区域-->
</ScrollView>

完整代码

jsx
// 重点A:阻止事件冒泡
handleTouchMove = (e) => {
  e.stopPropagation()
}
render() {
  return (
    <View className='rootClass' onTouchMove={this.handleTouchMove}>
      <!-- 遮罩层 --> 
      <View onClick={this.close} />
      <!-- 重点B: ScrollView(开启scrollY)--> 
      <ScrollView
        scrollY
        scrollX={false}
        className='layout-body__content'
        >
        <!-- 内容区域-->
    		<!-- 内容区域-->
        {this.props.children}
      </ScrollView>
    </View>
  )
}

最终效果

四、关于stopPropagation

JavaScript的事件流

简单来说:
JS中,冒泡和捕获是事件流的两种行为,
使用event.stopPropagation()可以起到阻止捕获和冒泡阶段中当前事件的进一步传播。
而使用event.preventDefault()可以取消默认事件。

事件流

事件流描述的是从页面中接受事件的顺序,分为

  • IE的事件流是 事件冒泡流,
  • 标准的浏览器事件流是 事件捕获流。