最后更新:2023-12-02
react-dnd组件使用教程
React DnD 是一组 React 高阶组件,使用的时候只需要使用对应的 API 将目标组件进行包裹,即可实现拖动或接受拖动元素的功能。将拖动的事件转换成对象中对应状态的形式,不需要开发者自己判断拖动状态,只需要在传入的 spec 对象中各个状态属性中做对应处理即可。
组件名字:react-dnd,一般还配合react-dnd-html5-backend,目前使用的版本:
1 2
| "react-dnd": "^9.5.1", "react-dnd-html5-backend": "^9.4.0",
|
1. 核心API介绍
- DragSource 用于包装你需要拖动的组件,使组件能够被拖拽(make it draggable)
- DropTarget 用于包装接收拖拽元素的组件,使组件能够放置(dropped on it)
下面是react-dnd: ^7.0.2,"react-dnd-html5-backend": "^7.0.2"版本的:
- DragDropContex 用于包装拖拽根组件,
DragSource 和 DropTarget 都需要包裹在DragDropContex内
- DragDropContextProvider 与
DragDropContex 类似,用 DragDropContextProvider 元素包裹拖拽根组件。
下面是"react-dnd": "^9.5.1","react-dnd-html5-backend": "^9.4.0"版本的:
- DndProvider 用
DndProvider 元素包裹拖拽根组件。
2. DragSource(type, spec, collect)参数介绍
1
| DragSource(type, spec, collect)
|
参数:
- type: 拖拽类型,必填
- spec: 拖拽事件的方法对象,必填
- collect: 把拖拽过程中需要信息注入组件的 props,接收两个参数
connect and monitor,必填
2.1 type参数说明
约定 source组件 为DragSource包装的组件,target组件 为DropTarget包装的组件
当 source组件的type 和 target组件的type 一致时,target组件可以接受source组件。
type的类型可以是 string,symbol,也可以是用一个函数来返回该组件的其他 props。
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12
| export default { BOX: 'box', }
import ItemTypes from './ItemTypes' @DragSource(ItemTypes.BOX, spec, collect)
import ItemTypes from './ItemTypes' @DropTarget(ItemTypes.BOX, spec, collect)
|
2.2spec参数说明
spec定义特定方法的对象,可以定义 拖动 相关的事件。
实际代码
package.json文件中添加包:
1 2
| "react-dnd": "^9.5.1", "react-dnd-html5-backend": "^9.4.0",
|
要拖动的组件使用DragSource包装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| import { DropTarget } from 'react-dnd'
const searchDragType = 'searchDragType'
const itemSpecSource = { canDrag() { return true }, beginDrag(props) { const { data } = props return { data, } }, endDrag() { } }
function collect(connect, monitor) { return { connectDragSource: connect.dragSource(), isDragging: monitor.isDragging() } }
const AtlasSearchListItem = function (connectDragSource) { return connectDragSource( <div className="map"> 数据</div> ) } AtlasSearchListItem.propTypes = { connectDragSource: PropTypes.func, } export default DragSource(searchDragType, itemSpecSource, collect)(AtlasSearchListItem)
|
接受拖动组件使用DropTarget包装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| import { DropTarget } from 'react-dnd'
const searchDragType = 'searchDragType'
const itemSpecTarget = { canDrop() { return true }, drop(props, monitor) { const { info } = props console.log('props: ', props) console.log('monitor.getItem(): ', monitor.getItem()) } }
function collect(connect, monitor) { return { connectDropTarget: connect.dropTarget(), canDrop: monitor.canDrop(), itemType: monitor.getItemType() } } class AtlasRightCard extends PureComponent { render() { const { connectDropTarget } = this.props return connectDropTarget( <div className="atlas-right-card-data-map"> </div> ) } }
AtlasRightCard.propTypes = { connectDropTarget: PropTypes.func, }
export default DropTarget(searchDragType, itemSpecTarget, collect)(AtlasRightCard)
|
使用DndProvider包裹上拖动、接受拖动的组件
在拖动组件、接受拖动的组件上一层使用DndProvider包裹上,来完成拖动
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import { DndProvider } from 'react-dnd' import HTML5Backend from 'react-dnd-html5-backend'
class Atlas extends PureComponent { render() { return ( <div className="data-map-atlas-mian-box-data-map"> <DndProvider backend={HTML5Backend}> <div className="content-main-box"> {/* 要拖动的组件 */} <AtlasSearchListItem /> {/* 接受拖动的组件 */} <AtlasRightPancel /> </div> </DndProvider> </div> ) } }
|
参考资料
react-dnd github
强大的拖拽组件:React DnD 的使用 segmentfault
react-dnd 用法详解 CSDN