antd table表头拖拽实现

文章目录

  • 前言
  • 一、安装 antd、react-resizable 第三方库
  • 二、使用步骤
    • 1、引入库
    • 2、配置
      • 2.1、配置表头拉伸组件:
      • 2.2、配置表格列columns:
      • 2.3、重新配置表格列,给予拉伸的方法:
      • 2.4、拉伸回调方法:
      • 2.5、自定义拖拽标志
    • 3、配置table组件
  • 三、效果
  • 拆分组件
  • 总结


前言

按需求我们需要把antd库中table表格的表头,设置为可拖拽的,在antd中并没有现成的属性方法,所以我们需要用到第三方库react-resizable

本文还封装了可拖拽表头的表格组件,其中有阻止冒泡防止拖拽时引起排序、选中文字等操作。如果你急需此功能,那么可以直接滑倒底部拿取代码


一、安装 antd、react-resizable 第三方库

yarn add antd react-resizable --save

二、使用步骤

1、引入库

代码如下:

import React, { useState } from 'react'
import { Table } from 'antd'
import { Resizable } from 'react-resizable'
import "react-resizable/css/styles.css"  // 一定要引入样式,否则没有拖拽的小标
// 当然我们也可以不引入,使用自定义拖拽标标,请看下面详情

2、配置

2.1、配置表头拉伸组件:

需要放在组件外部,否则每次拖拽无法更新!

// 可伸缩表头组件,放到组件外
const ResizableTitle = ({ onResize, width, ...restProps }) => {
    if (!width) { return (<th {...restProps} />) };

    return (
        <Resizable
            width={width}
            height={0}
            handle={
                <span
                    className="react-resizable-handle"
                    onClick={e => { e.stopPropagation() }}
                />
            }
            onResize={onResize}
            draggableOpts={{ enableUserSelectHack: false }}
        >
            <th {...restProps} style={{ ...restProps?.style, userSelect: 'none' }} />
        </Resizable>
    );
};

2.2、配置表格列columns:

// 表格数据
const dataSource = [
    { _id: 1, label: '范德萨1', gender: '男' },
    { _id: 2, label: '范德萨2', gender: '女' },
    { _id: 3, label: '范德萨3', gender: '男' },
    { _id: 4, label: '范德萨4', gender: '男' },
    { _id: 5, label: '范德萨5', gender: '女' },
]

// 表格列
const columns = [
    {
        title: '#',
        dataIndex: '_id',
        width: 60,
        ellipsis: true,
    },
    {
        title: '名称',
        dataIndex: 'label',
        width: 200,
        ellipsis: true,
    },
    {
        title: '性别',
        dataIndex: 'gender',
        width: 200,
        ellipsis: true,
    },
    {
        title: '操作',
        key: 'action',
       	// width: 200,
        ellipsis: true,
        render: () => (
            <a>修改</a>
        ),
    },
];

表格列的最后一列不要设置宽度,否则会引起拉伸就会触发以下异常!。

antd table表头拖拽实现_第1张图片

2.3、重新配置表格列,给予拉伸的方法:

// 可伸缩表头组件
const [column, setColumn] = useState(
    columns.map(it => {
      it.ellipsis = {
        showTitle: true
      }
      it.onHeaderCell = col => ({
        width: col.width,
        // !传入newColumn,而不传入column是因为需要拿到有onHeaderCell的值,外面collumn的变化内部监听不到
        onResize: (e, { size }) => handleResize(col, size),
      })
      return it;
    }
    )
  );

2.4、拉伸回调方法:

// table的th实时宽度拖拽的改变
  const handleResize = (col, size) => {
    setColumn(column.map(item => {
      // 如果这个判断对不上,列宽可以移动但是会引起错乱
      if (item.dataIndex === col.dataIndex) {
        item.width = size.width;
      }
      return item
    }))
  }

2.5、自定义拖拽标志

在css或less中设置对应的类名样式,也可以设置为自定义的拖拽图标

// 取消引入样式,通过设置类名,来设置拖拽的标志
.react-resizable-handle {
  	position: absolute;
  	right: -5px;
  	bottom: 0;
  	z-index: 1;
  	width: 10px;
  	height: 100%;
  	cursor: col-resize;
}

3、配置table组件

// table的th实时宽度拖拽的改变
 <Table 
 	rowKey={'_id'}
  	columns={column}
  	dataSource={dataSource}
  	components={{
    	header: {
      		cell: ResizableTitle,
     	},
  	}}
 ></Table>

三、效果

antd table表头拖拽实现_第2张图片

拆分组件

直接拿代码
components/ResizableTableModel/index.jsx

// components/ResizableTableModel/index.jsx
// 可拖拽表格组件
import { useState } from 'react';
import { Table } from 'antd';
import { Resizable } from 'react-resizable';
import './index.css';


// 表头拖拽组件
const ResizableTitle = ({ onResize, width, ...restProps }) => {
    if (!width) { return (<th {...restProps} />) };

    return (
        <Resizable
            width={width}
            height={0}
            handle={
                <span
                    className="react-resizable-handle"
                    onClick={e => { e.stopPropagation() }}
                />
            }
            onResize={onResize}
            draggableOpts={{ enableUserSelectHack: false }}
        >
            <th {...restProps} style={{ ...restProps?.style, userSelect: 'none' }} />
        </Resizable>
    );
};


// 带拖拽表格组件
const ResizableTable = ({ columns = [], ...props }) => {
  
    // * 列数据
    const [cols, setCols] = useState(columns);
    const colsArray = cols.map((col, index) => {
        return {
            ...col,
            onHeaderCell: column => ({ width: column.width, onResize: handleResize(index) })
        };
    });

    // todo 调整列宽
    const handleResize = index => {
        return (_, { size }) => {
            const temp = [...cols];
            temp[index] = { ...temp[index], width: size.width };
            setCols(temp);
        };
    };

    return (
        <Table
            components={{ header: { cell: ResizableTitle } }}
            columns={colsArray}
            {...props}
        />
    );
};

export default ResizableTable;

components/ResizableTableModel/index.css

// components/ResizableTableModel/index.css
.react-resizable-handle {
  	position: absolute;
  	right: -5px;
  	bottom: 0;
  	z-index: 1;
  	width: 10px;
  	height: 100%;
  	cursor: col-resize;
}

pages/home/index.jsx

// pages/home/index.jsx
import React from 'react'
import { Divider, Table } from 'antd'
import ResizeableTableModel from '@/components/ResizeableTableModel'


const dataSource = [
    { _id: 1, label: '范德萨1', gender: '男' },
    { _id: 2, label: '范德萨2', gender: '女' },
    { _id: 3, label: '范德萨3', gender: '男' },
    { _id: 4, label: '范德萨4', gender: '男' },
    { _id: 5, label: '范德萨5', gender: '女' },
]


const columns = [
    {
        title: '#',
        dataIndex: '_id',
        width: 60,
        ellipsis: true,
    },
    {
        title: '名称',
        dataIndex: 'label',
        width: 200,
        ellipsis: true,
    },
    {
        title: '性别',
        dataIndex: 'gender',
        width: 200,
        ellipsis: true,
    },
    {
        title: '操作',
        key: 'action',
        width: 200,
        ellipsis: true,
        render: () => (
            <a>修改</a>
        ),
    },
];



const Layout = () => {
    return (
        <>
             <Divider children="组件表格" />
             <ResizeableTableModel
                  rowKey={'_id'}
                  columns={columns}
                  dataSource={dataSource}
              />
        </>
    )
}

export default Layout

总结

要注意以下两点:

  • 1、初始列的宽度设置
  • 2、拖拽回调的判断赋值

制作不易,看完给小编点个赞吧!

你可能感兴趣的:(react,前端,javascript,前端,react.js,前端框架)