Wei Zhu
7 years ago
committed by
GitHub
9 changed files with 456 additions and 350 deletions
@ -0,0 +1,204 @@ |
|||
--- |
|||
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'; |
|||
} |
|||
} |
|||
|
|||
let BodyRow = (props) => { |
|||
const { |
|||
isOver, |
|||
connectDragSource, |
|||
connectDropTarget, |
|||
moveRow, |
|||
dragRow, |
|||
clientOffset, |
|||
sourceClientOffset, |
|||
initialClientOffset, |
|||
...restProps |
|||
} = props; |
|||
const 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( |
|||
<tr |
|||
{...restProps} |
|||
className={className} |
|||
style={style} |
|||
/> |
|||
) |
|||
); |
|||
}; |
|||
|
|||
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; |
|||
}, |
|||
}; |
|||
|
|||
BodyRow = 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: BodyRow, |
|||
}, |
|||
} |
|||
|
|||
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 ( |
|||
<Table |
|||
columns={columns} |
|||
dataSource={this.state.data} |
|||
components={this.components} |
|||
onRow={(record, index) => ({ |
|||
index, |
|||
moveRow: this.moveRow, |
|||
})} |
|||
/> |
|||
); |
|||
} |
|||
} |
|||
|
|||
const Demo = DragDropContext(HTML5Backend)(DragSortingTable); |
|||
|
|||
ReactDOM.render(<Demo />, 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; |
|||
} |
|||
```` |
Loading…
Reference in new issue