react-dnd
Posted 吃草的虾米
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了react-dnd相关的知识,希望对你有一定的参考价值。
介绍
React DnD 是一组 React 高阶组件,可以用来帮你构建复杂的拖拽接口,同时解耦你的组件。React DnD 非常适合像 Trello 和 Storify 这样的应用,在不同地方通过拖拽转移数据,而组件会改变它们的外观和应用的状态来响应拖拽事件。
基本用法
- 把应用的根组件包装在
DragDropContext
中 - 把可以拖拽的组件包装在
DragSource
中- 设置 type
- 设置 spec,让组件可以响应拖拽事件
- 设置 collect,把拖拽过程中需要信息注入组件的 props
- 把可以接受拖拽的组件包装在
DropTarget
中- 设置 type
- 设置 spec,让组件可以响应拖拽事件
- 设置 collect,把拖拽过程中需要信息注入组件的 props
- 完
翻译成代码就是:
// 1 import html5Backend from ‘react-dnd-html5-backend‘; import { DragDropContext } from ‘react-dnd‘; class App { ... } export default DragDropContext(HTML5Backend)(App); /*---------------------------*/ // 2 import { DragSource } from ‘react-dnd‘; class MyComponent { ... } export default DragSource(type, spec, collect)(MyComponent); /*---------------------------*/ // 3 import { DropTarget } from ‘react-dnd‘; class MyComponent2 { ... } export default DropTarget(types, spec, collect)(MyComponent2);
这样,MyComponent 就变得可以拖拽,而 MyComponent2 就变得可以接受拖拽了,但这并不代表 MyComponent 可以放到 MyComponent2 中!
一些概念
React DnD 中有一些特殊的概念,理解这些概念之后才能活用这个库!
Backend
实现 DnD 的方式,默认是用 HTML5 DnD API,它不能在触屏环境下工作,而且在 IE 下可定制性比其他浏览器弱。你也可以用自己实现,具体请看官方文档。Items
拖拽数据的表现形式,用 Object 来表示。譬如,要拖拽一张卡片,那这张卡片的数据的表现形式可能是{ id: xxx, content: yyy }
。Types
表示拖/放组件的兼容性,DragSource
和DropTarget
必须指定type
。只有在type
相同的情况下,DragSource
才能放到DropTarget
中。Monitors
用来响应拖拽事件,可以用来更新组件的的状态。Connectors
底层接触 DOM 的东西,用来封装你的组件,让你的组件有拖拽的特性。一般在 collect 方法中指定,然后注入到组件的 props 中,最后 render 方法中包装你自己的组件。DragSource && DropTarget
把上面的概念都绑在一起的东西,也是真正跟你的组件打交道的东西。
主要 API 介绍
这些主要 API 都是通过包装你的组件,然后返回一个新的组件。
DragDropContext(backend)
backend
实现 DnD 的方式,一般是 HTML5Backendexport default DragDropContext(HTML5Backend)(App);
DragSource(type, spec, collect)
DropTarget(type, spec, collect)
type
必须。type 是自定义的,可以是 string,symbol,也可以是用一个函数来返回该组件的其他 props。该组件只能放到相同 type 的 DropTarget 中。spec
必须。一个带有特定方法的纯 Object,里面是一些响应拖拽事件的方法。collect
必须。一个函数返回一个 Object,这个 Object 会注入到组件的 props 中。options
可选。除非有性能问题,否则不需要关心这个参数。const type = ‘xxx‘; const spec = { ... }; function collect(connect, monitor) { ... } export default DragSource(type, spec, collect)(MyComponent); export default DropTarget(type, spec, collect)(MyComponent2);
DragSource#spec
让你的组件响应 dnd 相关事件,支持以下方法:
beginDrag(props, monitor, component)
必须endDrag(props, monitor, component)
可选canDrag(props, monitor)
可选isDragging(props, monitor)
可选
参数含义如下:
props
组件当前的 propsmonitor
是一个DragSourceMonitor
实例,用来查询当前 drag state 的信息。component
表示当前组件,可以省略。const spec = { beginDrag(props) { return { id: props.id, content: props.content } } //... }
DropTarget#spec
让你的组件响应 dnd 相关事件,支持以下方法:
drop(props, monitor, component)
可选,响应 drop 事件hover(props, monitor, component)
可选canDrop(props, monitor)
可选
参数含义如下:
props
组件当前的 propsmonitor
是一个DropTargetMonitor
实例,用来查询当前 drag state 的信息。component
表示当前组件,可以省略。const spec = { drop(props, monitor, component) { // 获取正在拖放的数据 const item = monitor.getItem(); // 更新组件状态 component.setState({ item }) } }
DragSource#collect(connect, monitor)
DropTarget#collect(connect, monitor)
返回一个 object,这个 object 可以会注入到组件的 props 中。
connect
一个DragSourceConnector
/DropTargetConnector
实例,可以用connect.dragSource()
/connect.dropTarget()
来封装我们的组件。monitor
一个DragSourceMonitor
/DropTargetMonitor
实例,用来查询当前拖拽的信息。function collect(connect, monitor) { return { isDragging: monitor.isDragging(), connectDragSource: connect.dragSource() } } class MyComponent extends Component { render() { // 可以访问 collect 中返回的 object const { isDragging, connectDragSource } = this.props; // 需要用 connect.dragSource()/connect.dropTarget() 封装自己的组件 return connectDragSource( <div>123</div> ) } }
转自:https://scarletsky.github.io/2015/11/17/react-dnd-usage/
以上是关于react-dnd的主要内容,如果未能解决你的问题,请参考以下文章
react-dnd 的 connectDragPreview() 是如何工作的?
react-dnd 简单的可排序示例 ES6 而不是 ES7
使用 react-dnd 和 useDrag 和 useDrop 进行测试