基于React封装的可拖拽排序的表格组件

本文介绍了如何利用React封装一个可拖拽排序的表格组件。首先,安装相关依赖,然后提供组件的完整代码,接着在项目中引入组件,并调用SyncDataSource方法处理排序后的数据,例如保存排序结果。

废话不多说,直接开干~~~~

1、安装组件所需依赖:

    "react-dnd": "^10.0.2",
    "react-dnd-html5-backend": "^10.0.2",
    "immutability-helper": "^3.0.1",

2、组件全部代码如下<可直接复制使用>:

import React 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';

let dragingIndex = -1;
//判断2个数组是否相等
function ArrayIsEqual(arr1,arr2){
    //如果2个数组对应的指针相同,那么肯定相等,同时也对比一下类型
    if(arr1===arr2){
        return true;
    }else{
        if(arr1.length!=arr2.length){
            return false;
        }else{
            for(let i in arr1){
                //循环遍历对比每个位置的元素
                if(arr1[i]!=arr2[i]){
                    //只要出现一次不相等,那么2个数组就不相等
                    return false;
                }
            }
            //for循环完成,没有出现不相等的情况,那么2个数组相等
            return true;
        }
    }
}

class BodyRow extends React.Component {
    render() {
        const {isOver, connectDragSource, connectDropTarget, moveRow, ...restProps} = this.props;
        const style = {...restProps.style, cursor: 'move'};
        let {className} = restProps;
        if (isOver) {
            if (restProps.index > dragingIndex) {
                className += ' drop-over-downward';
            }
            if (restProps.index < dragingIndex) {
                className += ' drop-over-upward';
            }
        }
        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;
    if (dragIndex === hoverIndex) {
      return;
    }
    props.moveRow(dragIndex, hoverIndex);
    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),
);

export default class DraftSortTable extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            DataSource: [],
            props,
        }
    }

    static getDerivedStateFromProps(nextProps, prevState) {
		const {DataSource,Portion,} = nextProps;
        const {props} = prevState;
        if(DataSource && DataSource.length >= 0 && props && props.DataSource){
            //当传入的 DataSource '不等于' State 中的 DataSource 时,更新 State
            if(!ArrayIsEqual(DataSource,props.DataSource)){
                return {
                    DataSource,
                    props : {
                        DataSource,
                    },
                };
            };
        };
        //否则不对 State 进行操作
        return null;
    };

    Components = {
        body: {
            row: DragableBodyRow,
        },
    };

    /**
     * 表格拖拽函数
     */
    MoveRow = (dragIndex, hoverIndex) => {
        const {DataSource,} = this.state;
        const dragRow = DataSource[dragIndex];
        this.setState(
            update(this.state, {
                DataSource: {
                    $splice: [[dragIndex, 1], [hoverIndex, 0, dragRow]],
                },
            }),
        );
        this.SyncDataSource();
    };

    /**
     * 将新数组反传给父组件
     */
    SyncDataSource = () =>{
        const {DataSource,} = this.state;
        if (this.props.SyncDataSource) {
            this.props.SyncDataSource(DataSource,this.props.CGType,);
        }
    }

    render() {
        const {Columns,RowSelection,RowClassName,ClassName,RowKey,} =  this.props;
        const {DataSource,} = this.state;
        return (
            <DndProvider backend={HTML5Backend}>
                <Table
                    bordered
                    rowKey={RowKey}
                    columns={Columns}
                    pagination={false}
                    className={ClassName}
                    dataSource={DataSource}
                    rowSelection={RowSelection}
                    rowClassName={RowClassName}
                    components={this.Components}
                    onRow={(record, index) => ({
                        index,
                        moveRow: this.MoveRow,
                    })}
                />
            </DndProvider>
        );
    }
}

3、在需要用到拖拽表格组件的地方引用<具体地址以个人代码为准,建议写在components中>:

import DraftSortTable from "../../../components/DraftSortTable";

4、使用组件:

<DraftSortTable
    CGType={1}
    RowKey="ID"
    RowSelection={rowSelectionAR}
    Columns={columns_AR}
    DataSource={ARList}
    SyncDataSource = {this.SyncDataSource.bind(this)}
    RowClassName={(record, index) => {
        if (record.IsCite) {
            return "Expire editRow"
        }else {return "editRow"}
    }}
/>

5、根据需要写 SyncDataSource 方法

比如将排序结果存起来等...


END

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值