Skip to content

页面滚动

页面级滚动由页面和 Page 生命周期控制;局部滚动由 scroll-view 控制。一个页面应明确由谁承载主滚动,避免在页面滚动与纵向 scroll-view 之间嵌套竞争手势。

页面级滚动

滚动到指定位置

wx.pageScrollTo 用于控制整个页面的滚动位置,适合返回顶部、跳到章节和恢复阅读位置。

js
wx.pageScrollTo({
  scrollTop: 0,
  duration: 300,
})

需要滚到指定元素时,先通过 SelectorQuery 获取元素相对页面的位置,再调用 wx.pageScrollTo

js
const query = wx.createSelectorQuery()

query.select('#section-order').boundingClientRect()
query.selectViewport().scrollOffset()

query.exec(([rect, viewport]) => {
  if (!rect) return

  wx.pageScrollTo({
    scrollTop: viewport.scrollTop + rect.top,
    duration: 300,
  })
})

监听页面滚动

在页面的 onPageScroll 中获取滚动位置。常用于吸顶导航、滚动后显示返回顶部按钮,以及根据滚动距离调整导航栏样式。

js
Page({
  onPageScroll({ scrollTop }) {
    this.setData({ showBackToTop: scrollTop > 400 })
  },
})

滚动事件触发频繁,不要在回调中执行复杂计算或频繁请求;仅在状态变化时调用 setData

触底加载与下拉刷新

  • onReachBottom:页面触底时加载下一页数据;触发距离由页面配置 onReachBottomDistance 控制。
  • onPullDownRefresh:用户在页面顶部下拉时刷新数据;需在页面配置中启用 enablePullDownRefresh,完成后调用 wx.stopPullDownRefresh()
js
Page({
  async onPullDownRefresh() {
    try {
      await this.loadFirstPage()
    } finally {
      wx.stopPullDownRefresh()
    }
  },

  onReachBottom() {
    this.loadNextPage()
  },
})

分页请求应避免并发触发,并在没有更多数据时停止加载。

局部滚动:scroll-view

scroll-view 适合聊天记录、横向标签栏和固定头尾之间的列表区域。通过 scroll-topscroll-leftscroll-into-view 控制位置;通过 bindscrollbindscrolltolower 等事件响应滚动和触底。

局部列表的加载更多应监听 bindscrolltolower,而不是页面的 onReachBottom

xml
<scroll-view
  class="list"
  scroll-y
  scroll-into-view="{{activeId}}"
  bindscrolltolower="loadMore"
>
  <view wx:for="{{items}}" wx:key="id" id="item-{{item.id}}">
    {{item.name}}
  </view>
</scroll-view>

高度自适应

纵向 scroll-view 必须具有可确定的高度。固定区域与滚动区域共存时,可将页面设为纵向 flex 容器,并以 flex: 1 填充剩余空间。

xml
<view class="page">
  <swiper class="banner" indicator-dots>
    <swiper-item wx:for="{{banners}}" wx:key="id">
      <image src="{{item.image}}" mode="aspectFill" />
    </swiper-item>
  </swiper>

  <view class="scroll-wrapper">
    <scroll-view class="list" scroll-y bindscrolltolower="loadMore">
      <view wx:for="{{items}}" wx:key="id" class="card">{{item.name}}</view>
    </scroll-view>
  </view>
</view>
css
page {
  height: 100%;
}

.page {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.banner {
  height: 400rpx;
}

.scroll-wrapper {
  flex: 1;
  min-height: 0;
}

.list {
  height: 100%;
}

min-height: 0 允许 flex 子项收缩,避免内容撑开容器而无法滚动。

基于 MIT 许可发布