react 开源组件-无限滚动

95 阅读1分钟

定义变量

export interface InfiniteScrollProps {
  /**
   * @description 是否禁用
   * @default false
   */
  infiniteScrollDisabled?: Boolean;
  /**
   * @description 节流时延,单位为ms
   * @default 200
   */
  infiniteScrollDelay?: number;
  /**
   * @description 触发加载的距离阈值,单位为px
   * @default 0
   */
  infiniteScrollDistance?: number;
  /**
   * @description 是否立即执行加载方法,以防初始状态下内容无法撑满容器。
   * @default true
   */
  infiniteScrollImmediate?: Boolean;
}

实现过程

import React, { FC, memo, useState } from 'react';
import Css from './index.module.less';
import { InfiniteScrollProps } from './interface';

const InfiniteScroll: FC<InfiniteScrollProps> = memo(
  ({
    infiniteScrollDisabled,
    infiniteScrollDelay,
    infiniteScrollDistance,
    infiniteScrollImmediate,
  }) => {
    infiniteScrollDisabled = infiniteScrollDisabled ? infiniteScrollDisabled : false;
    infiniteScrollDelay = infiniteScrollDelay ? infiniteScrollDelay : 200;
    infiniteScrollDistance = infiniteScrollDistance ? infiniteScrollDistance : 0;
    infiniteScrollImmediate = infiniteScrollImmediate ? infiniteScrollImmediate : true;

    // 全局
    let n = 1;
    let [list, setList] = useState(getlist(10));

    function getlist(num: number) {
      let arr: any = [];
      for (let i = 0; i < num; i++) {
        arr.push(n++);
        console.log(n);
      }
      return arr;
    }

    function scroll(e: any) {
      let top = e.target.scrollTop;
      let height = e.target.offsetHeight;
      let heightSum = e.target.children[0].offsetHeight;

      if (top + height >= heightSum - infiniteScrollDistance) {
        if (infiniteScrollImmediate) {
          let newArr = getlist(2);
          let arr = [...list, ...newArr];
          setList(arr);
        } else {
          setTimeout(() => {
            let newArr = getlist(2);
            let arr = [...list, ...newArr];
            setList(arr);
          }, infiniteScrollDelay);
        }
      }
    }

    return (
      <div className={Css['infiniteScroll']} onScroll={(e: any) => scroll(e)}>
        <ul>
          {list.map((item: any, index: any) => {
            return <li>测试{index + 1}</li>;
          })}
        </ul>
      </div>
    );
  },
);

export default InfiniteScroll;

主要思路

判断每一个块距离底部的距离,若距离底部的距离+页面滚动的距离>=页面的总高度-用户自定义距离就加载下一页的,注意:用户页面渲染的是数组为一个响应式数据。