小程序頁面滾動穿透

小程序頁面滾動穿透

一、場景

  • 在項目當中,基礎遇到這樣的需求

有一個長列表,或者其他可滾動展示的頁面,
在這個頁面會彈出一個Modal層,如下:

貝殼找房的 的篩選欄

貝殼找房的

二、問題

如果這個彈框內容不可滾動,不會有太大問題;

但是當彈出內容是可以滾動的時候,就會有問題,

觸摸沒有滾動的區域會發現滾動可以穿透,會傳遞給下面的列表頁面,

三、解決辦法

程序員是面向Google編程的,找到了下面的解決辦法:

  • 監聽彈框狀態,如果彈框展示就給列表 添加對應樣式
 // isShowMask 彈框是否展示
 <view class="dog-container {{isShowMask ? 'bottom-fixed' : ''}}"></view>
.bottom-fixed {
    position: fixed;
    left: 0;
    top: 0;
    overflow: hidden;
}
  • 給遮罩層添加 catchtouchmove的阻止
myCatchTouch: function () {
    return;
}
<view wx:if="{{alert}}" catchtouchmove="myCatchTouch">
    <template is="alert" data="{{alertData}}" />
</view>

這樣的話,底部的列表內容就不會出現溢出,也自然不會滾動,

::: warning
但是,這樣的做法有一個弊端,

不會去記錄我之前訪問的位置,也就是每次點開彈框,列表位置會歸零,體驗終歸是不好的。
:::

四、升級方案

於是我去翻了一些開源小程序UI的Demo,去試試看這種彈框類型的交互,

最後發現在Taro UI中有一個組件,Float LayOu,是沒有出現穿透的,列表位置也沒有發生改變,

Taro UI 一套基於 Taro 框架開發的多端 UI 組件庫

  • 於是,我翻了源碼,發現他是這樣寫的(有刪減):
  // 重點A:阻止事件冒泡
  handleTouchMove = (e) => {
    e.stopPropagation()
  }
  render() {
    return (
      <View className='rootClass' onTouchMove={this.handleTouchMove}>
        <!-- 遮罩層 --> 
        <View onClick={this.close} className='at-float-layout__overlay' />
        <View className='at-float-layout__container layout'>
          <View className='layout-body'>
            <!-- 重點B: ScrollView(開啓scrollY)--> 
            <ScrollView
              scrollY
              scrollX={false}
              className='layout-body__content'
            >
              {this.props.children}
            </ScrollView>
          </View>
        </View>
      </View>
    )
  }
  • 思路解析:

i、首先,需要在自定義彈框的根元素,添加 onTouchMove 監聽,並阻止時間的冒泡


    <View className='rootClass' onTouchMove={this.handleTouchMove}>

ii、但是,裏面的內容,就不能滾動了,那麼,可以使用 ScrollView代替View,並開啓Y軸的滾動

    <ScrollView
        scrollY
        scrollX={false}
        className='layout-body__content'
    >
    <!-- 內容區域-->
    <!-- 內容區域-->
    </ScrollView>

按照這樣的思路,我在項目裏面嘗試了下,果然奏效,這樣的方式更優雅體驗也更好。

筆者使用了Taro,但原理都是一樣的。

  • 最終效果:
最終效果

五、關於stopPropagation

簡單來說:

::: tip
JavaScript中,冒泡和捕獲是事件流的兩種行爲,使用event.stopPropagation()可以起到阻止捕獲和冒泡階段中當前事件的進一步傳播。

而使用event.preventDefault()可以取消默認事件。
:::

事件流

事件流描述的是從頁面中接受事件的順序,分爲

  • IE的事件流是 事件冒泡流,

  • 標準的瀏覽器事件流是 事件捕獲流。

好了,希望對大家有用,對事件流有興趣的可以自行Google

或者看下這片文章:JavaScript的事件流


Ending…



csdn

github

個人站點

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章