创建项目
$ mkdir myapp && cd myapp
$ yarn create @umijs/umi-app
$ yarn add react-dnd react-dnd-html5-backend
简单了解 API
DndProvider
一个容器,在这个容器中的元素可以进行拖放的操作。
import { HTML5Backend } from 'react-dnd-html5-backend'
import { DndProvider } from 'react-dnd'
export default class YourApp {
render() {
return (
<DndProvider backend={HTML5Backend}>
/* Your Drag-and-Drop Application */
</DndProvider>
)
}
}
useDrag
一个 hook 函数,可以让一个 DOM 元素实现拖拽效果。
import { useDrag } from 'react-dnd'
function DraggableComponent(props) {
const [collectedProps, drag] = useDrag({
item: { id, type }
})
return <div ref={drag}>...</div>
}
useDrop
一个 hook 函数,可以让一个 DOM 元素能够放置拖拽元素。
import { useDrop } from 'react-dnd'
function myDropTarget(props) {
const [collectedProps, drop] = useDrop({
accept
})
return <div ref={drop}>Drop Target</div>
}
一个简单的栗子
import React from 'react';
import styles from './index.less';
import { useDrop, useDrag, DndProvider } from 'react-dnd'
import { HTML5Backend } from 'react-dnd-html5-backend'
const ItemTypes = {
APP: 'demo-app'
}
const Child = () => {
const [{ isDragging }, drag] = useDrag({
item: { type: ItemTypes.APP },
collect: (monitor) => ({
isDragging: monitor.isDragging(),
}),
})
return <div className={styles.child} style={{ opacity: isDragging ? 0.5 : 1 }} ref={drag}>
Child
</div>
}
const Container = () => {
const [{ isOver }, drag] = useDrop({
accept: ItemTypes.APP,
collect: (monitor) => ({
isOver: monitor.isOver(),
}),
})
return <div className={styles.container} ref={drag} style={{ background: isOver ? '#FFAA00' : '#FFFFFF' }}>
Container
</div>
}
export default () => {
return (
<DndProvider backend={HTML5Backend}>
<div className={styles.app}>
<Container />
<Child />
</div>
</DndProvider>
);
}
.app {
background: #FFFFFF;
}
.container {
border: #CCCCCC solid 1px;
width: 300px;
height: 300px;
}
.child {
border: #CCCCCC solid 1px;
display: inline-block;
margin: 5px;
width: 50px;
height: 50px;
}
用到的三个 API 梳理
简单梳理下所有的 API
useDrag
这个 hook 函数返回一个数组。
index 0
一个对象,它是从配置中的 collect 函数来定义的。
index 1
一个连接器函数,用在 React 的 ref 属性。连接了能够拖拽的元素。
index 2
一个连接器函数,用在 React 的 ref 属性。连接了会被拖拽的元素。
PS; 1 和 2 可以用来实现拖拽元素 A 中的元素 B,元素 A 跟着移动。
下面是 Hook 函数中的配置对象元素:
-
item
必填属性,它是一个纯 JavaScript 对象。这个对象中必须传的是 type 属性。另外的一个作用是传递拓转元素中的数据。可以在拓转完成函数end
中拿到数据做后续处理。 -
item.type
必填属性,只有 drag 和 drop 中的 type 相才能实现拖放。 -
previewOptions
预览配置对象? -
options
配置对象 -
begin(monitor)
拖拽开始事件,一般不需要返回,如果有 return 会替换 item -
end(item, monitor)
拖拽结束事件 -
canDrag(monitor)
定义能否拖拽的函数。 -
isDragging(monitor)
用于重写定义正在拖拽中的状态。,一般不用改。 -
collect
收集函数,必须返回一个对象。具体配置可参照 DragSourceMonitor,它返回的对象可以在index 0
对象中拿到。
个人感觉 item 和 collect 最常用,begin 函数和 end 函数也比较常用。梳理下来还是挺简单的。
useDrop
这个 hook 函数返回一个数组:
index 0
collect 函数返回的对象,如果没有对象可以返回空。
index 1
一个连接器函数,用在 React 的 ref 属性。连接了能够放置的元素。
下面是配置对象元素:
-
accept
必填项,定义了一个可以接收的拖拽元素的类型。(就是 useDrag 中的 item.type) -
options
配置对象 -
drop(item, monitor)
放置 drag 元素事件 -
hover(item, monitor)
drag 元素进入 drop 元素事件。 -
canDrop(item, monitor)
定义是否能否放置的函数。如果使用默认方式,不需要定义。 -
collect
收集函数,必须返回一个对象。具体配置参照 DropTargetMonitor,它返回的对象会出现在index 0
中
DndProvider
这是一个 React 容器组件,在这个容器组件中的元素才可以实现拖放。
它一共三个 props:
-
backend
必要属性,React Dnd backend,一般都会使用 HTML5 backend。 -
context
backend context 配置。具体要看 backend 库的定义。 -
options
backend 配置对象,具体要看 backend 库的定义。
最后
暂时就这么多,简单写了个 demo,然后了解了一下用到的 API。其实仔细了解之下还是蛮简单的。还有 useDragLayer 和 DragPreviewImage 两个 API 没用到,但应该都不难。
明天我试着写个更加复杂的例子分享出来。
网友评论