上拉加载 / 下拉刷新

1. 开源解决方案

社区主流:better-scroll。

使用 better-scroll 实现下拉刷新、上拉加载时要注意以下几点:

  • 容器需要固定高度,且需要包含一个内容 wrapper。
  • wrapper 高度需大于容器才会产生滚动。
  • 滚动方向、阈值、是否启用下拉刷新等通过配置项控制。
  • 初始化时机:DOM 渲染完成后调用 new BScroll(el, opts)。

2. 实现原理

上拉加载

触底判断公式:

scrollTop + clientHeight >= scrollHeight

简单实现:

const clientHeight = document.documentElement.clientHeight; // 浏览器高度
const scrollHeight = document.body.scrollHeight;
const scrollTop = document.documentElement.scrollTop;

const distance = 50; // 距视窗底部 50px 时开始触发

if (scrollTop + clientHeight >= scrollHeight - distance) {
  console.log('开始加载数据');
}

下拉刷新

下拉刷新的本质是:页面本身置于顶部时,用户下拉时触发的动作。

原生实现主要分为三步:

  1. 下拉过程:记录手指起点位置、当前下拉距离,显示提示文案(如"下拉刷新")。
  2. 临界点判断:超过阈值时进入"可释放刷新"状态。
  3. 松手刷新:用户松手后触发请求,成功后隐藏刷新提示并复位 UI。

下拉到松手的过程会经历三个阶段:

  1. 下拉中(未到阈值)
  2. 可释放(到达阈值)
  3. 刷新中(松手后,发起请求)

补充:现代移动端实现上拉加载 / 下拉刷新时,常配合:

  • IntersectionObserver:监听某个 sentinel 元素进入视口,自动触发加载。
  • 防抖 / 节流:避免高频滚动事件。
  • 虚拟列表:数据量大时避免 DOM 节点过多。
// IntersectionObserver 触底加载示例
const sentinel = document.querySelector('#sentinel');
const io = new IntersectionObserver((entries) => {
  if (entries[0].isIntersecting) {
    loadMore();
  }
});
io.observe(sentinel);

来源整理自:我的有道云笔记