1.0.1 • Published 2 months ago

@wont/use-antd-resizable-header v1.0.1

Weekly downloads
-
License
MIT
Repository
github
Last release
2 months ago

use-antd-resizable-header

extend from https://github.com/hemengke1997/use-antd-resizable-header, cause no one approval pull request and publish, details #81 feat: custom dragRender

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

预览

preview

在线地址

Demo

安装

npm i use-antd-resizable-header

or

yarn add use-antd-resizable-header

or

pnpm add use-antd-resizable-header

API

Properties

NameTypeDefaultDescription
columnsColumnType[]undefinedantd table 的 columns
defaultWidthnumber120某一列不能拖动,设置该列的最小展示宽度,默认 120
minConstraintsnumber60拖动最小宽度 默认 defaultWidth/2
maxConstraintsnumberInfinity拖动最大宽度 默认无穷
cachebooleantrue是否缓存宽度,避免渲染重置拖拽宽度
columnsStateColumnsStateTypeundefined列状态的配置,可以用来操作列拖拽宽度
onResizeStartFunctionundefined开始拖拽时触发
onResizeEndFunctionundefined结束拖拽时触发
tooltipRenderFunctionundefined使用tooltip渲染表格头,当表格头文字溢出时展示tooltip
dragRenderReactNodesvg左右拖动dom控制表头拖拽节点
dragWrapperStyleCSSPropertiesundefineddragRender的父元素内联样式

Return

NameDescription
resizableColumns拖拽 columns,用在 Table columns
components拖拽 components, 用在 Table components
tableWidth表格宽度,用在 Table width
resetColumns重置宽度方法

注意事项

  • 默认拖动颜色为#000,可通过global或设置 css 变量--arh-color设置颜色
  • 至少一列不能拖动(width 不设置即可),请保持至少一列的自适应
  • 若 column 未传入dataIndex,请传入一个唯一的key,否则按照将按照 column 的序号 index 计算唯一 key
  • 若 column 有副作用,请把依赖项传入 useMemo deps 中

Break-Change

  • v2.9.0起,不需要再手动引入css样式文件
  • 请安装 use-antd-resizable-header,而非 @minko-fe/use-antd-resizable-header

Example

import ProTable from "@ant-design/pro-table";
import { Button, Table, Tooltip } from "antd";
import { useAntdResizableHeader } from "use-antd-resizable-header";

function App() {
  const columns: ColumnsType<object> = [];
  const { components, resizableColumns, tableWidth, resetColumns } =
    useAntdResizableHeader({
      columns: useMemo(() => columns, []),
      // 保存拖拽宽度至本地localStorage
      columnsState: {
        persistenceKey: "localKey",
        persistenceType: "localStorage",
      },
      tooltipRender: (props) => <Tooltip {...props} />,
    });

  const proColumns: ProColumns[] = [];
  const {
    components: proComponents,
    resizableColumns: proResizableColumns,
    tableWidth: proTableWidth,
    resetColumns: proResetColumns,
  } = useAntdResizableHeader({
    columns: useMemo(() => proColumns, []),
    tooltipRender: (props) => <Tooltip {...props} />,
  });

  return (
    <>
      <Table
        columns={resizableColumns}
        components={components}
        dataSource={data}
        scroll={{ x: tableWidth }}
      />
      <ProTable
        columns={proResizableColumns}
        components={proComponents}
        dataSource={data}
        scroll={{ x: proTableWidth }}
      />
      <Button onClick={() => resetColumns()}>重置宽度</Button>
    </>
  );
}

基本用例

/* index.css */
--arh-color: red;
import { Space, Table, Tag } from "antd";
import React, { useReducer } from "react";
import { useAntdResizableHeader } from "use-antd-resizable-header";

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 Example: React.FC = () => {
  const [, forceRender] = useReducer((s) => s + 1, 0);
  const [deps, setDeps] = useState(0);

  const columns = [
    {
      title: "Name",
      dataIndex: "name",
      key: "name",
      width: 300,
      ellipsis: true,
      render: (text) => (
        <a onClick={() => setDeps((t) => t + 1)}>
          {text}
          {deps}
        </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 } = useAntdResizableHeader({
    columns: useMemo(() => columns, [deps]),
    minConstraints: 50,
  });

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

为什么需要 React.useMemo ?

如果不使用 useMemo

组件 render => columns 引用变化 => use-antd-resiable-header render => 组件 render => columns 引用变化···

不使用 useMemo

可以采用其他阻止 render 的方案,如: columns 是 prop 或 组件外常量

Table 特殊处理

filter 按钮溢出隐藏了

解决方案

.ant-table-filter-trigger {
  margin-inline: 0;
}

ProTable 特殊处理

fixed

ProTable 默认会给 fixed 列添加宽度,所以可能会造成 至少一列宽度为0 的条件无法满足。

解决方案

  1. 手动给 fixed 列添加宽度,然后不设置其余某一个非 fixed 列宽度
  2. 不设置 fixed 列宽度(默认 200),然后其余某一列也不设置宽度

本地开发

# 开发调试工具库
pnpm i

pnpm run dev

# 预览调试 playground
cd playground

pnpm i

pnpm run dev

MIT

LICENSE