react antdesign table 添加滚动加载(下拉翻页功能);table 定位实现简单介绍

1. 逻辑功能简单介绍

  1. 逻辑并不复杂,首先获取到表格中可滚动那一级dom元素,然后监听它的滚动;当滚动到底了则触发我们自己的函数;
  2. 全篇幅最主要的一点就是 useEffect 中的内容,其他的都是看你怎么来了;
  3. useEffect 内容简单介绍:
    (1)findNeedNode 函数: 递归查找 Table 元素中 className 为 ant-table-body 的节点(可滚动那一级dom元素)
    (2)找到元素后添加监听滚动;
    (3)判断屏幕高度和滚动条的高度,达到条件后则触发父级传入过来的滚动函数;
    (4)功能拓展:实现了 findNeedNode 函数,其实就相当于实现了在ui框架组件内查找任意首次出现的 className。这里举个例子,比如说在 Table 中实现定位到某条内容;改装 findNeedNode函数,固定查找 ant-table-body className 修改为可传入式;定位到某条内容需要获取到这条内容的所在盒子的高度,而表格内部内容不可控,所以说需要获取表格内所有内容的高度进行加法运算(此处运算到需要定位的内容就停止),得到高度后,获取到 Table 中 tr 上一级的节点,设置这个节点的 scrollTop 属性进行定位。
  4. 注意如果想要出现滚动条需要设置 scroll 属性 给如 父级的高度就行了(document.getElementById(‘tableFather’)?.clientHeight)
  5. 如果介意代码野的可以看看总结的第三点和第四点
  6. 这块个人建议别看了,因为这块没有虚拟列表的优化,页面卡顿得厉害;去看看我虚拟列表实现吧
  7. React之antdesign官网虚拟列表二次封装(涵盖虚拟列表滚动加载)

2. 实现

import { useState, useEffect, useRef } from 'react';
import { Table } from 'antd'
const defaultTableInfo = {
  loading: false,
  tableData: [],
  tableConfig: [
	{
      title: '名字',
      dataIndex: 'name',
      width: '180px',
      align: 'center',
      render: (text, record, index) => text
    },
  ],
  pagination: {
    pageNum: 1,
    pageSize: 10,
    total: 0
  }
}
const renderNumber = 0;
const Table = (props) => {
  const { scroll, tableInfo = defaultTableInfo, onScrollBottom } = props;
  const [pagination, setPagination] = useState(tableInfo.pagination);
  const [columns, setColumns] = useState<any>(tableInfo.tableConfig);

  const tableRef = useRef<any>(null)
  useEffect(() => {
    if (tableInfo.loading) return;
    // 获取可滚动节点的父级节点
    const findNeedNode: any = (node: any) => {
      // 这个判断逻辑是看界面节点找到的可滚动那一级
      if (node.className === 'ant-table-body') return node;
      if (node.children) {
      	// 这块内容可以理解为数组中的map操作 return [].map(v=>xxxx);为啥不用map的原因是needNode不是一个真正的数组;
        let needNode: any = [];
        node.children.forEach((child: any) => {
          needNode.push(findNeedNode(child))
        })
        return needNode;
      }
    }
    setTimeout(() => {
   	  // 最终处理完成的数据不知道在多少维;就当是N维数组;以flat(Infinity)降维处理;
      const dom = findNeedNode(tableRef.current).flat(Infinity)[0];
      // 
      if (!dom) return;
      // 监听 屏幕是否到底了;
      if (renderNumber > 1) return;
      // 加载数据完毕后 只渲染第一次(addEventListener只让他生效一次!!!)
      renderNumber++;
      dom.addEventListener("scroll", () => {
        const { pageSize, pageNum, total } = tableInfo.pagination;
        const all = pageSize * pageNum;
        const scrollTop = dom.scrollTop;
        // 变量windowHeight是可视区的高度
        const windowHeight = dom.clientHeight || dom.clientHeight;
        // 变量scrollHeight是滚动条的总高度
        const scrollHeight = dom.scrollHeight || dom.scrollHeight;
        if (scrollTop + windowHeight + 1 > scrollHeight) {
          if (all < total) {
            // 表格置空不能有滚动加载
            if (tableInfo.tableData.length < 1) return;
            // 触发到底的函数
            onScrollBottom({ ...pagination, pageNum: pageNum + 1 });
          }
        }
      });
    }, 0);
  }, [tableInfo.loading])
  return <Table
            size="small"
            rowKey="uuid"
            ref={tableRef}
            loading={tableInfo.loading}
            pagination={false}
            scroll={scrollInner}
            columns={columns.filter((item: any) => !item.hidden)}
            dataSource={tableInfo.tableData}
          />
}

3. 功能拓展

  1. findNeedNode 功能拓展:可查找ui框架内任意首次出现的className节点(温馨提示:此递归也可改成查找任意出现过的className)
const findNeedNode: any = (node: any, key: string = 'ant-table-body') => {
  if (node.className === key) return node;
  if (node.children) {
    let needNode: any = [];
    node.children.forEach((child: any) => {
      needNode.push(findNeedNode(child, key))
    })
    return needNode;
  }
}
  1. 定位功能可自己实现(有问题可以在评论区询问);

总结

  1. 上面代码是目测的,应该没有具体问题,反正中心点跟着我的介绍走,然后参考上面的示例,一般不会出啥问题。
  2. 如果有其他方法可以一起探讨一下!
  3. 上面这个因为使用了 addEventListener 所以说会有一个蛇皮问题,此组件如果有任何更新操作会导致整个组件重新渲染(别担心,正常一两三四五个表格在同一个页面根本看不出来,只是这个操作感觉很野的感觉),因为 react 是在全局的 document 上做的事件处理,我这个操作算是破坏这个流程的感觉,这块我倒是不知道咋个解决了,有大佬知道的求告知。
  4. 第三点的问题综合起来就是:在ui库里面的某个元素添加节点事件监听(addEventListener)后会出现的问题;
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值