react + better-scroll 实现下拉刷新 上拉加载更多

1.封装组件

components/Scroll/index.tsx

/**
 * 下拉刷新 上拉加载更多
*/
import React, { forwardRef, useState,useEffect, useRef, useImperativeHandle, useMemo } from "react"
import PropTypes from "prop-types"
import BScroll from "better-scroll"
import Loading from '../loading/index';
import Loading2 from '../loading-v2/index';
import debounce from "utils/debounce";
import './index.less';

const Scroll = forwardRef((props:any, ref:any) => {
  const [bScroll, setBScroll] = useState<any>();

  const scrollContaninerRef:any = useRef();

  const { direction, click, refresh, pullUpLoading, pullDownLoading, bounceTop, bounceBottom } = props;

  const { pullUp, pullDown, onScroll } = props;

  let pullUpDebounce = useMemo(() => {
    return debounce(pullUp, 500)
  }, [pullUp]);

  let pullDownDebounce = useMemo(() => {
    return debounce(pullDown, 500)
  }, [pullDown]);

  useEffect(() => {
    const scroll:any = new BScroll(scrollContaninerRef.current, {
      scrollX: direction === "horizental",
      scrollY: direction === "vertical",
      probeType: 3,
      click: click,
      bounce:{
        top: bounceTop,
        bottom: bounceBottom
      }
    });
    setBScroll(scroll);
    return () => {
      setBScroll(null);
    }
    // eslint-disable-next-line
  }, []);

  useEffect(() => {
    if(!bScroll || !onScroll) return;
    bScroll.on('scroll', onScroll)
    return () => {
      bScroll.off('scroll', onScroll);
    }
  }, [onScroll, bScroll]);

  useEffect(() => {
    if(!bScroll || !pullUp) return;
    const handlePullUp = () => {
      //判断是否滑动到了底部
      if(bScroll.y <= bScroll.maxScrollY + 100){
        pullUpDebounce();
      }
    };
    bScroll.on('scrollEnd', handlePullUp);
    return () => {
      bScroll.off('scrollEnd', handlePullUp);
    }
  }, [pullUp, pullUpDebounce, bScroll]);

  useEffect(() => {
    if(!bScroll || !pullDown) return;
    const handlePullDown = (pos: any) => {
      //判断用户的下拉动作
      if(pos.y > 50) {
        pullDownDebounce();
      }
    };
    bScroll.on('touchEnd', handlePullDown);
    return () => {
      bScroll.off('touchEnd', handlePullDown);
    }
  }, [pullDown, pullDownDebounce, bScroll]);


  useEffect(() => {
    if(refresh && bScroll){
      bScroll.refresh();
    }
  });

  useImperativeHandle(ref, () => ({
    refresh() {
      if(bScroll) {
        bScroll.refresh();
        bScroll.scrollTo(0, 0);
      }
    },
    getBScroll() {
      if(bScroll) {
        return bScroll;
      }
    }
  }));

  const PullUpdisplayStyle = pullUpLoading ? { display: "" } : { display: "none" };
  const PullDowndisplayStyle = pullDownLoading ? { display: "" } : { display: "none" };
  return (
    <div className="scroll_container" ref={scrollContaninerRef}>
      {props.children}
      {/* 滑到底部加载动画 */}
      <div className="pull_up_loading" style={ PullUpdisplayStyle }><Loading></Loading></div>
      {/* 顶部下拉刷新动画 */}
      <div className="pull_down_loading" style={ PullDowndisplayStyle }><Loading2></Loading2></div>
    </div>
  );
})

Scroll.defaultProps = {
  direction: "vertical",
  click: true,
  refresh: true,
  onScroll:null,
  pullUpLoading: false,
  pullDownLoading: false,
  pullUp: null,
  pullDown: null,
  bounceTop: true,
  bounceBottom: true
};

Scroll.propTypes = {
  direction: PropTypes.oneOf(['vertical', 'horizental']),
  refresh: PropTypes.bool,
  onScroll: PropTypes.func,
  pullUp: PropTypes.func,
  pullDown: PropTypes.func,
  pullUpLoading: PropTypes.bool,
  pullDownLoading: PropTypes.bool,
  bounceTop: PropTypes.bool,//是否支持向上吸顶
  bounceBottom: PropTypes.bool//是否支持向下吸顶
};

export default Scroll;

2.页面调用

import Scroll from 'components/Scroll';
...
<Scroll 
  // onScroll={forceCheck}
  pullUp={handlePullUp}
  pullDown={handlePullDown}
  ref={scrollRef}
  pullUpLoading={pullUpLoading}
  pullDownLoading={pullDownLoading}
>
  <ul className="list_content clearfix">
    {
      searchList.toJS().map((item:any) =>{
        return (
          <li key={item.comic_id}>
            <Link to={"/categoryPage/category/detail?id=" + item.comic_id}>
              <img src={item.cover} alt="" />
              <span className="category_txt clearfix">
                <strong>{item.title}</strong>
                <span>
                  <em>{item.message}</em>
                  <em>{item.good}</em>
                </span>
              </span>
            </Link>
          </li>
        )
      })
    }
  </ul>
</Scroll>

.

原文地址:https://www.cnblogs.com/crazycode2/p/12589226.html