ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

antd表格拖拽

2021-09-29 17:34:59  阅读:141  来源: 互联网

标签:index hover const 表格 dataList id sameList antd 拖拽


antd表格拖拽

组件DragSortableTable

支持合并单元格拖拽

import React, { useState, useEffect } from 'react';
import { Table } from 'antd';
import { DndProvider, DragSource, DropTarget } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
import update from 'immutability-helper';

import { isFunction } from '@/utils/types';
import styles from './index.less';

let dragingIndex = -1;

const BodyRow = ({ isOver, connectDragSource, connectDropTarget, moveRow, ...restProps }) => {
    const style = { ...restProps.style, cursor: 'move' };

    let { className } = restProps;
    if (isOver) {
        if (restProps.index > dragingIndex) {
            className += ` ${styles.dropOverDownward}`;
        }
        if (restProps.index < dragingIndex) {
            className += ` ${styles.dropOverUpward}`;
        }
    }

    return connectDragSource(connectDropTarget(<tr {...restProps} className={className} style={style} />));
};

const rowSource = {
    beginDrag(props) {
        dragingIndex = props.index;
        return {
            index: props.index,
        };
    },
};

const rowTarget = {
    drop(props, monitor) {
        const dragIndex = monitor.getItem().index;
        const hoverIndex = props.index;

        // Don't replace items with themselves
        if (dragIndex === hoverIndex) {
            return;
        }

        // Time to actually perform the action
        props.moveRow(dragIndex, hoverIndex);

        // Note: we're mutating the monitor item here!
        // Generally it's better to avoid mutations,
        // but it's good here for the sake of performance
        // to avoid expensive index searches.
        monitor.getItem().index = hoverIndex;
    },
};

const DragableBodyRow = DropTarget('row', rowTarget, (connect, monitor) => ({
    connectDropTarget: connect.dropTarget(),
    isOver: monitor.isOver(),
}))(
    DragSource('row', rowSource, connect => ({
        connectDragSource: connect.dragSource(),
    }))(BodyRow),
);

const DragSortableTable = ({
    dataSource,
    columns,
    onSort,
    groupDrag = false, // 是否支持组拖拽
    groupDragOrder = 'name', // 合并名称,必传,否则组拖拽会出问题
    identifies = 'id', // 唯一标识,必传,否则组拖拽会出问题
    ...restProps
}) => {
    const [dataList, setDataList] = useState([]);
    const [columnsList, setColumnsList] = useState([]);
    useEffect(() => {
        if (Array.isArray(dataSource)) {
            setDataList(dataSource);
        }
    }, [dataSource]);
    useEffect(() => {
        if (Array.isArray(columns)) {
            setColumnsList(columns);
        }
    }, [columns]);

    const components = {
        body: {
            row: DragableBodyRow,
        },
    };
    const moveRow = (dragIndex, hoverIndex) => {
        const dragRow = dataList[dragIndex];
        if (groupDrag) {
            // 拖拽元素
            const rowName_drag = dataList[dragIndex][groupDragOrder];
            // 目标元素
            const rowName_hover = dataList[hoverIndex][groupDragOrder];
            // 拖拽元素项
            // const rowName_drag_item = dataList[dragIndex];
            // 目标元素项
            const rowName_hover_item = dataList[hoverIndex];
            // 拖拽元素相同项
            const sameList_drag = dataList.filter(el => el[groupDragOrder] === rowName_drag);
            // 拖拽元素不同项
            const notSameList_drag = dataList.filter(el => el[groupDragOrder] !== rowName_drag);
            // 目标元素相同项
            const sameList_hover = dataList.filter(el => el[groupDragOrder] === rowName_hover);
            // 目标元素不同项
            const notSameList_hover = dataList.filter(el => el[groupDragOrder] !== rowName_hover);
            // 目标组
            if (sameList_hover.length > 1) {
                // 拖拽组
                if (sameList_drag.length > 1) {
                    notSameList_drag.splice(
                        sameList_hover.map((item, index) => ({ ...item, index }))[0].index,
                        0,
                        ...sameList_drag,
                    );
                } else {
                    let flag = 0;
                    sameList_hover.forEach((v, index) => {
                        if (rowName_hover_item[identifies] === v[identifies]) {
                            flag = index;
                        }
                    });
                    const changeNotSameList_hover = notSameList_hover.filter(
                        h => h[groupDragOrder] !== dragRow[groupDragOrder],
                    );
                    let dedIndex = 0; // 目标index
                    // 组start
                    if (flag === 0) {
                        sameList_hover.splice(0, 0, dragRow);
                        notSameList_hover.forEach((v, index) => {
                            if (sameList_hover[0][identifies] === v[identifies]) {
                                dedIndex = index;
                            }
                        });
                        changeNotSameList_hover.splice(dedIndex, 0, ...sameList_hover);
                    } else {
                        // 组end
                        sameList_hover.splice(0, 0, dragRow);
                        notSameList_hover.forEach((v, index) => {
                            if (sameList_hover[[sameList_hover.length - 1]][identifies] === v[identifies]) {
                                dedIndex = index;
                            }
                        });
                        changeNotSameList_hover.splice(dedIndex, 0, ...sameList_hover);
                    }
                    setDataList(changeNotSameList_hover);
                    if (isFunction(onSort)) onSort(changeNotSameList_hover);
                    return;
                }
            } else {
                notSameList_drag.splice(hoverIndex, 0, ...sameList_drag);
            }
            setDataList(notSameList_drag);
            if (isFunction(onSort)) onSort(notSameList_drag);
            return;
        }
        const sortedDataList = update(dataList, {
            $splice: [
                [dragIndex, 1],
                [hoverIndex, 0, dragRow],
            ],
        });
        setDataList(sortedDataList);
        if (isFunction(onSort)) onSort(sortedDataList);
    };

    return (
        <DndProvider backend={HTML5Backend}>
            <Table
                className={styles.dragSortableTable}
                columns={columnsList}
                dataSource={dataList}
                components={components}
                onRow={(_, index) => ({
                    index,
                    moveRow,
                })}
                {...restProps}
            />
        </DndProvider>
    );
};

export default DragSortableTable;

.dragSortableTable {
    tr.dropOverDownward {
        td {
            border-bottom: 2px dashed #1890ff;
        }
    }

    tr.dropOverUpward {
        td {
            border-bottom: 2px dashed #1890ff;
        }
    }
}

使用

import React, { useState, useMemo } from 'react';
import DragSortableTable from './DragSortableTable';
/*
 *  参数text :为当前单元格的值 > string
 *	参数data :为当前table 渲染的数据 >数组
 *	参数key  : 为当前单元格的dataindex> string
 *	参数index :为当前单元格的第几行 >Number
 *  参数row :为table 当前行的数据对象  >Object
 */
const mergeCells = (text, data, key, index, row) => {
    //	如果相等则该单元格被上一列合并,直接返回rowSpan为 0
    if (index !== 0 && text === data[index - 1][key]) {
        return 0;
    }
    let rowSpan = 1;
    for (let i = index + 1; i < data.length; i++) {
        if (text !== data[i][key]) {
            break;
        } else {
            rowSpan++;
        }
    }
    return rowSpan;
};
export default () => {
    const list = [
        {
            id: '1',
            name: '组1',
            age: 32,
            address: 'New York No. 1 Lake Park',
            tags: ['nice', 'developer'],
        },
        {
            id: '2',
            name: '组1',
            age: 42,
            address: 'London No. 1 Lake Park',
            tags: ['loser'],
        },
        {
            id: '3',
            name: '组3',
            age: 32,
            address: 'Sidney No. 1 Lake Park',
            tags: ['cool', 'teacher'],
        },
        {
            id: '4',
            name: '组4',
            age: 32,
            address: 'Sidney No. 1 Lake Park',
            tags: ['cool', 'teacher'],
        },
        {
            id: '44',
            name: '组4',
            age: 32,
            address: 'Sidney No. 1 Lake Park',
            tags: ['cool', 'teacher'],
        },
        {
            id: '5',
            name: '组5',
            age: 32,
            address: 'Sidney No. 1 Lake Park',
            tags: ['cool', 'teacher'],
        },
        {
            id: '005',
            name: '组5',
            age: 32,
            address: 'Sidney No. 1 Lake Park',
            tags: ['cool', 'teacher'],
        },
        {
            id: '6',
            name: '组6',
            age: 32,
            address: 'Sidney No. 1 Lake Park',
            tags: ['cool', 'teacher'],
        },
        {
            id: '7',
            name: '组7',
            age: 32,
            address: 'Sidney No. 1 Lake Park',
            tags: ['cool', 'teacher'],
        },
    ];
    const [dataList, setDataList] = useState([...list]);

    // const [columns, setColumns] = useState([...defColumns]);
    const columns = useMemo(() => {
        const defColumns = [
            {
                title: 'ID',
                dataIndex: 'id',
                key: 'id',
            },
            {
                title: 'Name',
                dataIndex: 'name',
                key: 'name',
                render: (text, row, index) => {
                    if (dataList.length) {
                        return {
                            children: <span>{text}</span>,
                            props: {
                                rowSpan: mergeCells(text, dataList, 'name', index, row),
                            },
                        };
                    }
                },
            },
            {
                title: 'Age',
                dataIndex: 'age',
                key: 'age',
            },
            {
                title: 'Address',
                dataIndex: 'address',
                key: 'address',
            },
        ];
        return defColumns;
    }, [dataList]);
    const tableProps = {};

    return (
        <DragSortableTable
            {...tableProps}
            pagination={false}
            dataSource={dataList}
            columns={columns}
            bordered
            rowKey="id"
            groupDrag
            groupDragOrder="name"
            identifies="id" // 唯一标识,必传,否则组拖拽会出问题
            onSort={data => {
                // const ids = data.map(e => e.id);
                setDataList([...data]);
            }}
        />
    );
};

标签:index,hover,const,表格,dataList,id,sameList,antd,拖拽
来源: https://blog.csdn.net/waillyer/article/details/120552765

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有