移动端h5页面如何实现上拉加载,下拉刷新

下拉刷新(Pull-to-Refresh)与上拉加载(Infinite Scroll)的定义

下拉刷新‌:用户手指向下滑动屏幕时触发数据刷新的交互设计,主要用于‌重新加载最新内容‌(如新消息、动态更新)。

上拉加载‌:用户滑动到页面底部时自动加载更多数据的交互模式,用于‌分批次加载历史内容‌(如商品列表、新闻分页)。

核心作用对比

特性下拉刷新上拉加载
触发方向屏幕顶部向下滑动触发‌屏幕底部向上滑动触发‌
数据流向加载最新数据(时间倒序)‌加载更多历史数据(时间正序)‌
用户需求即时获取最新信息(如微博、聊天列表)‌浏览更多内容(如电商商品、长列表)‌

 实现方案

JavaScript Touch

一、Touch 事件基本类型与触发机制

四大核心事件

touchstart‌: 手指首次接触屏幕时触发,用于捕获触摸起点‌

touchmove‌: 手指在屏幕上滑动时持续触发,常用于实现拖动或滑动效果‌

touchend‌: 手指离开屏幕时触发,标记触摸结束‌

touchcancel‌: 系统中断触摸时触发(如来电、弹窗打断),需处理异常中断场景‌

事件触发顺序
典型流程为 touchstart → touchmove → touchend。若中途发生中断,则触发 touchcancel 替代 touchend‌。

二、TouchEvent 对象关键属性

通过事件回调参数可获取 ‌TouchEvent‌ 对象,其包含以下关键数据:

  • touches‌: 当前屏幕上所有触点的列表(包含多指触控信息)‌
  • targetTouches‌: 当前元素上活动的触点集合‌
  • changedTouches‌: 触发当前事件的触点集合(如 touchend 事件中记录刚移除的触点)‌
三、与鼠标事件的对比与兼容处理
  1. 行为差异

    • 移动端优先响应 touch 事件,随后可能触发 mouse 事件(如 click)‌5
    • click 事件在移动端有 ‌200-300ms 延迟‌(历史设计为区分单击与双击缩放)‌5
  2. 替代方案
    可通过自定义 ‌tap 事件‌ 消除延迟,示例实现逻辑:

function bindTap(element, callback) {
  let startTime = 0, isMove = false;
  element.addEventListener('touchstart', () => startTime = Date.now());
  element.addEventListener('touchmove', () => isMove = true);
  element.addEventListener('touchend', (e) => {
    if (!isMove && Date.now() - startTime < 200) callback(e);
  });
}

此方法通过判断触点移动状态和时间差模拟即时点击‌

技术实现关键点

  1. ‌下拉刷新

    • 触发条件‌:滑动距离超过阈值(如 60px)且释放手指‌
    • 加载状态‌:显示加载动画(如转圈图标)和提示文案(“正在刷新...”)‌
    • 数据更新‌:向服务器请求最新数据,清空或覆盖旧数据‌
<div class="refresh-container">
  <div class="refresh-indicator">↓ 下拉刷新</div>
  <div class="content">页面内容</div>
</div>
// 存储触摸起始点的 Y 坐标
let startY = 0;
// 标识是否正在刷新中(防止重复触发)
let isRefreshing = false;
const container = document.querySelector('.refresh-container');
// 提示文本元素
const indicator = document.querySelector('.refresh-indicator');

container.addEventListener('touchstart', e => {
// 如果正在刷新 或 页面不在顶部,直接返回(避免误触)
  if (isRefreshing || document.documentElement.scrollTop > 0) return;
// 记录初始触摸点的 Y 坐标(用于计算滑动距离)
  startY = e.touches.pageY;
});

container.addEventListener('touchmove', e => {
// 同上:防止刷新中或页面滚动时触发
  if (isRefreshing || document.documentElement.scrollTop > 0) return;
 // 计算滑动距离(当前 Y 坐标 - 起始 Y 坐标)
  const moveY = e.touches.pageY - startY;
// 仅处理下拉动作(moveY > 0 表示向下滑动)
  if (moveY > 0) {
/ 通过 CSS transform 移动容器位置(实现视觉下拉效果)
    container.style.transform = `translateY(${moveY}px)`;
// 根据滑动距离切换提示文本
    indicator.textContent = moveY > 50 ? "↑ 释放刷新" : "↓ 下拉刷新";
  }
});

container.addEventListener('touchend', async e => {
// 计算最终滑动距离(使用 changedTouches 确保触摸点已结束)
  const moveY = e.changedTouches.pageY - startY;
// 满足条件:滑动超过 50px 且未在刷新中
  if (moveY > 50 && !isRefreshing) {
 // 锁定刷新状态
    isRefreshing = true;
    indicator.textContent = "加载中...";
    await fetchData();  // 数据请求
    container.style.transform = "translateY(0)";// 复位容器位置
    indicator.textContent = "↓ 下拉刷新";
    isRefreshing = false;  // 释放刷新锁
  }
});

扩展优化方向

  1. 滑动阻力效果

// 添加阻力系数(如滑动距离超过 100px 时减速)
const dampenedY = moveY > 100 ? 100 + (moveY - 100) * 0.5 : moveY;
container.style.transform = `translateY(${dampenedY}px)`;

 ‌2.加载成功/失败提示

try {
  await fetchData();
  indicator.textContent = "加载成功!";
} catch (error) {
  indicator.textContent = "加载失败,请重试";
}

3. ‌动画复位效果

container.style.transition = "transform 0.3s ease"; // 添加复位动画
container.style.transform = "translateY(0)";

2.上拉加载

1. 滚动监听方案
//标记当前是否正在加载数据,防止重复请求
let isLoading = false;
//监听页面滚动事件,使用 throttle 节流函数,控制触发频率为 200ms(固定时间间隔内只执行一次(这里是每200ms))
window.addEventListener('scroll', throttle(() => {
//scrollTop:滚动条垂直偏移量(已滚动距离)
//clientHeight:可视区域高度(不包含滚动条)
//scrollHeight:整个文档的总高度(包含不可见部分)
  const { scrollTop, clientHeight, scrollHeight } = document.documentElement;
  const threshold = 100; // 距离底部100px触发
  
  if (scrollTop + clientHeight >= scrollHeight - threshold && !isLoading) {
    isLoading = true;
    loadMoreData().finally(() => isLoading = false);
  }
}, 200));

// 节流函数
function throttle(fn, delay) {
  let timer = null;
  return (...args) => {
    if (!timer) {
      timer = setTimeout(() => {
        fn.apply(this, args);
        timer = null;
      }, delay);
    }
  };
}

 2. IntersectionObserver API(现代浏览器支持)

Intersection Observer API‌ 是一种用于‌异步监测目标元素与视口(或指定父容器)交叉状态‌的浏览器原生 API,可高效实现以下功能:


核心特性

  1. 异步监听

    • 基于浏览器渲染线程独立工作,避免主线程阻塞
    • 替代传统 scroll 事件 + getBoundingClientRect 计算
  2. 高性能

    • 自动优化多元素监测,无需手动计算位置
    • 适用于无限滚动、图片懒加载等高频场景
  3. 灵活配置

    • 支持设置触发阈值 (threshold)、根容器 (root)、边距 (rootMargin) 等参数
<div class="loader">加载中...</div>

 

const observer = new IntersectionObserver(entries => {
  if (entries.isIntersecting && !isLoading) {
    isLoading = true;
    loadMoreData().finally(() => isLoading = false);
  }
});

observer.observe(document.querySelector('.loader'));

 

核心注意事项

问题类型解决方案
iOS橡皮筋效果添加CSS代码:body { overscroll-behavior: contain; }
安卓兼容性在touchmove事件中调用 e.preventDefault() 阻止默认滚动行为
频繁触发请求使用节流(throttle)/防抖(debounce) + 请求锁(loading状态)
内容高度不足当页面高度未占满屏幕时,自动触发首次加载
快速滑动白屏添加加载骨架屏(Skeleton Screen)优化体验

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值