React Hooks实现下拉刷新功能

2,277 阅读2分钟

一、踩坑

最近产品一直想要在h5页面里加一个下拉刷新的功能,活来了就得干呀。

20190414201232_mSruIq.jpg

先是找了比较火的better-scroll,但是不尽人意呀,奈何页面交互太多,使用better-scroll反而带出了一堆bug

better-scroll禁止了原生的click事件,想要content可以click,需要在初始化的时候配置。我配置完之后,click事件都触发两次,bug不就来了吗,比如弹窗,点一次,事件触发两次,相当于没弹

看文档说嵌套的better-scroll才会派发两次click,我没嵌套呀。。。算了还得自己来

二、设计

首先梳理一下整个功能点,参考app中的下拉刷新。 有下拉动作,页面下移,不能无限下拉,有阈值,到了一定阈值就拉不动了。 松手后回弹,停留指定位置,出现加载动作,页面还原

  1. 监听touchstart事件,记录手指对应文档上边缘距离PageY
const handleTouchStart = useCallback(e => {
    const [touches = {}] = e.changedTouches;
    const { pageY } = touches;

    setStartY(pageY);
}, []);
  1. 监听touchmove事件,当content scrollTop为0,并且此时differ = currPageY - startPageY,differ大于0时,说明时下拉动作,对应增加页面的translateY = differ,从而实现页面下移
const handleTouchMove = useCallback(e => {
    const [touches] = e.changedTouches;
    const { pageY } = touches;

    if (viewRef?.current) {
      const { scrollTop } = viewRef.current;
      const differ = pageY - startY;

      if (scrollTop === 0 && differ > 0) {
        setTop(differ);
      }
    }
}, [startY]);
  1. 监听页面touchend事件,设置一个阈值,当下拉超过阈值,设置translateY = stop,执行回调函数,函数执行完成,设置translateY = 0,还原页面
const handleTouchEnd = useCallback(e => {
    const [touches] = e.changedTouches;
    const { pageY } = touches;

    if (viewRef?.current) {
      const { scrollTop } = viewRef.current;
      const differ = pageY - startY;

      if (scrollTop === 0 && differ > 20) { // 下拉超过阈值
        setTop(stop);
        setDynamic(true);
        refresh().then(() => {
          setTimeout(() => {
            setTop(0);
            setDynamic(false);
          }, loadingTime);
        }).catch(() => {
          setTimeout(() => {
            setTop(0);
            setDynamic(false);
          }, loadingTime);
        });
      } else {
        setTop(0);
      }
    }
}, [stop, startY, loadingTime, refresh]);

三、实现

先看下效果

实际实现的时候做了一些改进:

  1. 下拉到阈值后,越拉页面下移得越小,值到拉不动,这里使用了log10函数计算。
  2. 增加loading时间,有时候刷新接口很快返回,loading效果刚出就结束了,会有闪一下的感觉

到这里基本就完成了,完整代码可以参考这里