--- order: 25 title: en-US: Drag sorting zh-CN: 拖拽排序 --- ## zh-CN 使用自定义元素,我们可以集成 react-dnd 来实现拖拽排序。 ## en-US By using custom components, we can integrate table with react-dnd to implement drag sorting. ````jsx import { Table } from 'antd'; import { DragDropContext, DragSource, DropTarget } from 'react-dnd'; import HTML5Backend from 'react-dnd-html5-backend'; import update from 'immutability-helper'; function dragDirection( dragIndex, hoverIndex, initialClientOffset, clientOffset, sourceClientOffset, ) { const hoverMiddleY = (initialClientOffset.y - sourceClientOffset.y) / 2; const hoverClientY = clientOffset.y - sourceClientOffset.y; if (dragIndex < hoverIndex && hoverClientY > hoverMiddleY) { return 'downward'; } if (dragIndex > hoverIndex && hoverClientY < hoverMiddleY) { return 'upward'; } } class BodyRow extends React.Component { render() { const { isOver, connectDragSource, connectDropTarget, moveRow, dragRow, clientOffset, sourceClientOffset, initialClientOffset, ...restProps } = this.props; const style = { ...restProps.style, cursor: 'move' }; let className = restProps.className; if (isOver && initialClientOffset) { const direction = dragDirection( dragRow.index, restProps.index, initialClientOffset, clientOffset, sourceClientOffset ); if (direction === 'downward') { className += ' drop-over-downward'; } if (direction === 'upward') { className += ' drop-over-upward'; } } return connectDragSource( connectDropTarget( ) ); } } const rowSource = { beginDrag(props) { 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(), sourceClientOffset: monitor.getSourceClientOffset(), }))( DragSource('row', rowSource, (connect, monitor) => ({ connectDragSource: connect.dragSource(), dragRow: monitor.getItem(), clientOffset: monitor.getClientOffset(), initialClientOffset: monitor.getInitialClientOffset(), }))(BodyRow) ); const columns = [{ title: 'Name', dataIndex: 'name', key: 'name', }, { title: 'Age', dataIndex: 'age', key: 'age', }, { title: 'Address', dataIndex: 'address', key: 'address', }]; class DragSortingTable extends React.Component { state = { data: [{ key: '1', name: 'John Brown', age: 32, address: 'New York No. 1 Lake Park', }, { key: '2', name: 'Jim Green', age: 42, address: 'London No. 1 Lake Park', }, { key: '3', name: 'Joe Black', age: 32, address: 'Sidney No. 1 Lake Park', }], } components = { body: { row: DragableBodyRow, }, } moveRow = (dragIndex, hoverIndex) => { const { data } = this.state; const dragRow = data[dragIndex]; this.setState( update(this.state, { data: { $splice: [[dragIndex, 1], [hoverIndex, 0, dragRow]], }, }), ); } render() { return ( ({ index, moveRow: this.moveRow, })} /> ); } } const Demo = DragDropContext(HTML5Backend)(DragSortingTable); ReactDOM.render(, mountNode); ```` ````css #components-table-demo-drag-sorting tr.drop-over-downward td { border-bottom: 2px dashed #1890ff; } #components-table-demo-drag-sorting tr.drop-over-upward td { border-top: 2px dashed #1890ff; } ````