自学内容网 自学内容网

react中实现拖拽排序

效果图:如下

效果说明:

        1. 点击“选择”按钮,打开弹窗

        2. 左侧数据是调接口回显来的

        3. 点击左侧某条数据,这条被点击的数据就会被添加到右侧

        4. 右侧的数据可以上下拖动换位置

        5.  右侧有数据时,点击"确定" 按钮,数据就会以字符串拼接形式回显到TextArea框里,以顿号(、)分割 

        6. antd3里面的拖拽组件用的 react-dnd的

<DndProvider backend={HTML5Backend}> 。但在我这项目里DndProvider就不适用(项目react版本16.8.6),换一种react-dnd的低版本的写法即DragDropContext

        7. 还有一些样式的问题,没写全,需要细调

         

        

代码难免会涉及到业务需求,展示部分代码,全部复制不能实现效果,仅供参考

1. 父

import React, { PureComponent } from 'react'
import { Row, Input, Button, Modal, Spin } from 'antd'
import DragSortingTable from './DragSortingTable' // 拖拽组件

const TextArea = Input.TextArea;

class SelectProject extends PureComponent {
    constructor(props){
        super(props)
        this.state= {
            modalVisible: false,
            loading: false,
            disabled: false,
            rightList: [],
            leftList: [],
            value: '',
        }
    }

    // 打开弹窗
    openModal = () => {
        this.setState({ modalVisible: true })
    }
    
    // 关闭弹窗
    onCloseModal = () => {
        this.setState({ modalVisible: false })
    }

    // 确定
    onOkModal = () => {
        const { rightList } = this.state;
        let stringData = ''
        rightList && rightList.forEach((item, index) => {
            if(index < rightList.length -1){
                stringData += `${item.destOrgName}`
            } else {
                stringData += item.destOrgName
            }
        })
        this.setState({ modalVisible: false, value: stringData })

    }

    // 点击左侧数据
    okDataClick = (item) => {
        const { rightList } = this.state;
        let list = JSON.parse(JSON.stringify(rightList))
        if(JSON.stringify(list).indexOf(JSON.stringify(item)) > -1){
            message.warning(`已选择${item.destOrgName}`)
            return false;
        }
        list.push(item)
        this.setState({ rightList: list })
    }

    // 左侧数据展示
    treeLeftList = () => {
        const { leftList } = this.state;
        const radioLeftList = []
        if(leftList[0]){
            leftList.forEach(item => {
                radioLeftList.push(
                    <div onClick={() => this.okDataClick(item)} style={{ lineHeight: '24px', padding: '4px 0', cursor: 'pointer' }}>{item.destOrgName}</div>
                )
            })
        }
        return radioLeftList
    }

    // 拖拽后,更新右侧数据
    updataSetState = (newData) => {
        this.setState({ rightList: newData })
    }

    // 删除当前行数据
    clearHang = (item) => {
       const { rightList } = this.state;
        const radioLeftList = []
        rightList.map(subItem => {
            if(subItem.destOrgName !== item.destOrgName){
                radioLeftList.push(subItem)
            }
        })
        this.setState({ rightList: radioLeftList })
    }

    // 左右两列整体展示
    buttonForm = () => {
        const { rightList } = this.state;
        return (
            <div>
                <Row>
                    <Col span={12}>
                        <span>选择xx</span>
                        <div>{this.treeLeftList()}</div>
                    </Col>
                    <Col span={12}>
                        <div><span>已选中xx</span><a>清空</a></div>
                        <div>
                            <DragSortingTable2 rightList={rightList} updata={this.updataSetState} clearHang={this.clearHang} /> // 重点:用的antd3的表格可拖拽
                        </div>
                    </Col>
                </Row>
            </div>
        )
    }

    render () {
        return (
            <div>
                <Row>
                    <TextArea autoSize disabled={} value={this.state.value} />
                    <Button 
                        onClick={() => {
                            this.setState({ 
                                 modalVisible: true,
                                loading: true,
                             }); this.openModal()
                            }}
                        disabled={this.state.disabled}
                    >选择</Button>
                </Row>

                { this.state.modalVisible ?
                    <Modal 
                        title='' 
                        visible={this.state.modalVisible} 
                        maskCloseable={false}
                        width='60%' 
                        onCancel={this.onCloseModal} 
                        footer={
                            <div style={{ textAlign: 'center'}}>
                                <Button onClick={this.onOkModal} type='primary'>确定</Button>
                                <Button onClick={this.onCloseModal}>关闭</Button>
                            </div>
                        }
                    >
                        <Spin spin={this.state.loading} tip='Loading'>
                            {this.buttonForm()}
                        </Spin>
                    </Modal> : null
                }
            </div>
        )
    }

}

export default SelectProject

拖拽子组件

相当于拖拽的table组件全部复制过来,然后主要改动是moveRow,和render里面的。

        1. 至于table有表格样式,就把表格样式设置border: 0   

        2. 页码不显示pagination={false}

        3. 当table没数据时,会显示一个空数据的图标,把空数据图标隐藏起来:z-index: -2

2. 子

import { Table } from 'antd';
import { DragDropContext, DragSource, DropTarget } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';

let dragingIndex = -1;

class DragSortingTable extends PureComponent {
    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;

    // 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),
);



class DragSortingTable extends React.Component {

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

    // 拖拽
  moveRow = (dragIndex, hoverIndex) => {
    const {rightList, updataSetState} = this.props;
    const dragRow = rightList[dragIndex];
    const newDataList = [...rightList]
    newDataList.splice(dragIndex, 1)
    newDataList.splice(hoverIndex, 0, dragRow)
    updataSetState(newDataList)
  };


  render() {
    
    const columns = [
      {
        title: <span style={{fontSize:'12px', color: '#71bbff'}}>{'长按可拖动排序'}</span>,
        dataIndex: 'destOrgName',
        key: 'destOrgName',
        render: (text, record) => {
            return (
                <span>{text}</span>
                <a onClick={() => this.props.clearHang(record)} style={{ float:'right'}}>x</a>
            )
        }
      }
    ];

    return (
        <Table
          columns={columns}
          dataSource={this.props.rightList} // 父级传过来的
          components={this.components}
          onRow={(record, index) => ({
            index,
            moveRow: this.moveRow,
          })}
          pagination={false} // 不显示页码
          className='dataListTable'
        />
    );
  }
}

}

const DragSortingTable2 = DragDropContext(HTML5Backend)(DragSortingTable)
export default DragSortingTable2


原文地址:https://blog.csdn.net/qq_47305413/article/details/144700173

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!