React DnD 是一组 React 高阶组件,能够用来帮你构建复杂的拖拽接口,同时解耦你的组件。React DnD 很是适合像 Trello 和 Storify 这样的应用,在不一样地方经过拖拽转移数据,而组件会改变它们的外观和应用的状态来响应拖拽事件。html
把应用的根组件包装在 DragDropContext
中html5
把能够拖拽的组件包装在 DragSource
中react
设置 typegit
设置 spec,让组件能够响应拖拽事件github
设置 collect,把拖拽过程当中须要信息注入组件的 props浏览器
把能够接受拖拽的组件包装在 DropTarget
中app
设置 type函数
设置 spec,让组件能够响应拖拽事件性能
设置 collect,把拖拽过程当中须要信息注入组件的 propsthis
完
翻译成代码就是:
// 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 都是经过包装你的组件,而后返回一个新的组件。
backend
实现 DnD 的方式,通常是 HTML5Backend
export default DragDropContext(HTML5Backend)(App);
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);
让你的组件响应 dnd 相关事件,支持如下方法:
beginDrag(props, monitor, component)
必须
endDrag(props, monitor, component)
可选
canDrag(props, monitor)
可选
isDragging(props, monitor)
可选
参数含义以下:
props
组件当前的 props
monitor
是一个 DragSourceMonitor
实例,用来查询当前 drag state 的信息。
component
表示当前组件,能够省略。
const spec = { beginDrag(props) { return { id: props.id, content: props.content } } //... }
让你的组件响应 dnd 相关事件,支持如下方法:
drop(props, monitor, component)
可选,响应 drop 事件
hover(props, monitor, component)
可选
canDrop(props, monitor)
可选
参数含义以下:
props
组件当前的 props
monitor
是一个 DropTargetMonitor
实例,用来查询当前 drag state 的信息。
component
表示当前组件,能够省略。
const spec = { drop(props, monitor, component) { // 获取正在拖放的数据 const item = monitor.getItem(); // 更新组件状态 component.setState({ item }) } }
返回一个 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> ) } }