React中的表格行数据的滚动吸附可视区 【bysking 】

312 阅读1分钟

React中,Antd组件库的table / proTable 如何实现针对某一行数据,向上滚动到顶部的时候吸附在顶部,向下滚动到底部的时候吸附在下面


  • 未吸附状态:

image.png


  • 吸附顶部状态:

image.png


  • 吸附底部状态:

image.png

import { ProTable } from '@ant-design/pro-components';
import { useEffect, useRef, useState } from 'react';

const StickyRowTable = () => {
  const tableRef = useRef<any>();
  const [stickyRowIndex, setStickyRowIndex] = useState(null);
  const stickItemKey = 12;

  const columns = [
    { title: '序号', dataIndex: 'key', key: 'key' },
    { title: 'Name', dataIndex: 'name', key: 'name' },
  ];

  const data = Array(200)
    .fill(1)
    .map((_, index) => ({ key: index, name: 'name' + index }));

  useEffect(() => {
    const handleScroll = () => {
      if (tableRef.current) {
        const tableBody = tableRef.current.querySelector('.ant-table-body');
        const rows = tableBody.querySelectorAll('.ant-table-row')[3];
        const tableRect = tableBody.getBoundingClientRect();

        for (let i = 0; i < rows.length; i++) {
          const rowRect = rows[i].getBoundingClientRect();
          if (rowRect.top <= tableRect.top && rowRect.bottom >= tableRect.top) {
            setStickyRowIndex(i);
            return;
          }
        }
        setStickyRowIndex(null);
      }
    };

    let tableWrapper = tableRef.current?.querySelector('.ant-table-body');

    tableWrapper.addEventListener('scroll', handleScroll);

    return () => {
      tableWrapper.removeEventListener('scroll', handleScroll);
    };
  }, []);

  const components = {
    body: {
      row: (props) => {
        const isSticky = props['data-row-key'] === stickItemKey;
        return (
          <tr
            {...props}
            style={{
              position: isSticky ? 'sticky' : 'static',
              top: isSticky ? 0 : 'auto',
              bottom: isSticky ? 0 : 'auto',
              zIndex: isSticky ? 1 : 'auto',
              backgroundColor: isSticky ? '#f0f0f0' : '#fff',
            }}
          />
        );
      },
    },
  };

  return (
    <div
      ref={(rr) => {
        tableRef.current = rr;
      }}
    >
      <ProTable
        columns={columns}
        dataSource={data}
        components={components}
        scroll={{ y: 300, x: 'max-content' }}
        pagination={false}
      />
    </div>
  );
};

export default StickyRowTable;

喜欢帮忙点个赞加关注支持,持续输出多种复杂场景的解决方案小技巧