uar

use-antd-resizable-header

antd表格头拖拽hook

Showing:

Popularity

Downloads/wk

133

GitHub Stars

8

Maintenance

Last Commit

8d ago

Contributors

2

Package

Dependencies

7

License

MIT

Type Definitions

Built-In

Tree-Shakeable

Yes?

Categories

Readme

use-antd-resizable-header

antd 表格头拖拽 Hook,兼容 Table ProTable

预览

preview

在线地址

codesandbox

安装

yarn add use-antd-resizable-header

最佳实践

为了规避循环渲染问题,建议:

  • columns 为常量时,提到组件外,或使用 React.useMemo, React.useRef 包裹常量
  • 更建议, 封装 table 组件,把 columns 作为 prop 传入
function ResizableTable<DataType extends Record<string, any>>(props: TableProps<DataType>) {
  const { columns: columnsProp, scroll, ...rest } = props;

  const { resizableColumns, components, tableWidth } = useATRH({
    columns: columnsProp,
    minConstraints: 50,
  });

  return (
    <Table
      columns={columns}
      scroll={{ ...scroll, x: tableWidth }}
      components={components}
      {...rest}
    ></Table>
  );
}

注意事项

  • 默认拖动颜色为#000,可通过global或设置 css 变量--atrh-color设置颜色
  • 至少一列不能拖动(width 不设置即可),请保持最后至少一列的自适应
  • 若 column 未传入dataIndex,请传入一个唯一的key,否则按照将按照 column 的序号 index 计算唯一 key

Example

import useATRH from 'use-antd-resizable-header';
import 'use-antd-resizable-header/dist/style.css';

const columns = [];

function App() {
  const { components, resizableColumns, tableWidth } = useATRH({ columns });

  return (
    <>
      <Table
        columns={resizableColumns}
        components={components}
        dataSource={data}
        scroll={{ x: tableWidth }}
      ></Table>
      <ProTable
        columns={resizableColumns}
        components={components}
        dataSource={data}
        scroll={{ x: tableWidth }}
      ></ProTable>;
    </>
  );
}

基本用例

/* index.css */
--atrh-color: red;
import React, { useReducer } from 'react';
import { Table, Tag, Space } from 'antd';
import useATRH from 'use-antd-resizable-header';
import 'antd/dist/antd.css';
import 'use-antd-resizable-header/dist/style.css';

const data = [
  {
    key: '1',
    name: 'John Brown',
    age: 32,
    address: 'New York No. 1 Lake Park',
    tags: ['nice', 'developer'],
  },
  {
    key: '2',
    name: 'Jim Green',
    age: 42,
    address: 'London No. 1 Lake Park',
    tags: ['loser'],
  },
  {
    key: '3',
    name: 'Joe Black',
    age: 32,
    address: 'Sidney No. 1 Lake Park',
    tags: ['cool', 'teacher'],
  },
];

const Hello: React.FC = () => {
  const [, forceRender] = useReducer((s) => s + 1, 0);

  const columns = React.useMemo(() => {
    return [
      {
        title: 'Name',
        dataIndex: 'name',
        key: 'name',
        width: 300,
        ellipsis: true,
        render: (text) => <a>{text}</a>,
      },
      {
        title: 'Age',
        dataIndex: 'age',
        key: 'age',
        ellipsis: true,
        width: 200,
      },
      {
        title: 'Address',
        dataIndex: 'address',
        key: 'address',
        ellipsis: true,
        width: 200,
      },
      {
        title: 'Tags',
        key: 'tags',
        dataIndex: 'tags',
        width: 200,
        ellipsis: true,
        render: (tags) => (
          <>
            {tags.map((tag) => {
              let color = tag.length > 5 ? 'geekblue' : 'green';
              if (tag === 'loser') {
                color = 'volcano';
              }
              return (
                <Tag color={color} key={tag}>
                  {tag.toUpperCase()}
                </Tag>
              );
            })}
          </>
        ),
      },
      {
        title: 'render',
        key: 'action',
        render: (text, record) => (
          <Space size="middle">
            <a>Invite {record.name}</a>
            <a
              onClick={() => {
                forceRender();
                alert('render');
              }}
            >
              render
            </a>
          </Space>
        ),
      },
    ];
  }, []);

  const { components, resizableColumns, tableWidth } = useATRH({
    columns,
    minConstraints: 50,
  });

  return (
    <Table
      columns={resizableColumns}
      components={components}
      dataSource={data}
      scroll={{ x: tableWidth }}
    />
  );
};

export default Hello;

基本用例 - 搭配 Typography 实现 title 溢出时 tooltip

/* index.css */
--atrh-color: red;
// utils.tsx
export const genEllipsis = (text: string, copyable?: boolean, stopPropagation?: boolean) => {
  let _text = isNil(text) ? '' : String(text);

  if ([null, undefined, ''].includes(text)) _text = '-';

  return (
    <Typography.Text
      style={{
        width: '100%',
        margin: 0,
        padding: 0,
        color: 'inherit',
      }}
      onClick={(e) => (stopPropagation ? e?.stopPropagation() : null)}
      title=" "
      copyable={
        copyable && text
          ? {
              text,
              tooltips: ['', ''],
            }
          : undefined
      }
      ellipsis={text ? { tooltip: text } : false}
    >
      {_text}
    </Typography.Text>
  );
};
// index.tsx
import ProTable from '@ant-design/pro-table'; // or import { Table } from 'antd'
import useATRH from 'use-antd-resizable-header';
import { genEllipsis } from './utils.tsx';

import 'use-antd-resizable-header/dist/style.css';
import './index.css';

const columns: ProColumns[] = [
  {
    title: 'id',
    dataIndex: 'id',
    width: 300,
    ellipsis: true,
  },
  {
    title: 'name',
    dataIndex: 'name',
    ellipsis: true,
  },
];

const dataSource = [
  {
    id: 1,
    name: 'zhangsan',
  },
  {
    id: 2,
    name: 'lisi',
  },
];

function App() {
  const { resizableColumns, components, tableWidth } = useATRH({ columns });

  let cols = [...resizableColumns];

  cols = columns.map((item) => ({
    ...item,
    title: genEllipsis(item.title as string, false, true),
  }));

  return (
    <ProTable
      columns={cols}
      components={components}
      scroll={{ x: tableWidth }}
      dataSource={dataSource}
    ></ProTable>
  );
}

export default App;

TODO

  • 测试用例

MIT

LICENSE

Rate & Review

Great Documentation0
Easy to Use0
Performant0
Highly Customizable0
Bleeding Edge0
Responsive Maintainers0
Poor Documentation0
Hard to Use0
Slow0
Buggy0
Abandoned0
Unwelcoming Community0
100