dnd-kit 我称之为拖拽组件中的王者
用过react-dnd和react-beautiful-dnd都没有dnd-kit组件灵活以及暴露的数据多(也可能是我研究的不够深)
使用场景及可实现功能
实现画布类拖拽
- 元素能否被拖拽
- 元素区域能否被拖入(data数据应用)
- 元素区域能否被拖出(data数据应用)
- 元素区域可接收哪些类型的元素拖入(data数据应用)
- 定位元素拖拽(碰撞算法内可做处理)
拖拽类组件大差不差,有dragContext、drop、drag组件,浅显理解context实现数据共享,drop为可被拖拽的区域,drag为可被拖拽的元素
使用方式看文章,不做讲解
<DndContext
// dndkit自带碰撞算法,不传则默认为rectIntersection
// collisionDetection={rectIntersection}
// collisionDetection={pointerWithin}
/**
* 碰撞算法优化
* 自定义碰撞算法
*/
collisionDetection={customCollisionDetectionStrategy} ‘
/**
* 传感器配置
*/
sensors={sensors}
onDragStart={res => {
console.log({ onDragStartMove: res });
// 自己打印看吧
}}
onDragEnd={(res: DragEndEvent) => {
console.log({ onDragEnd: res });
// 拖拽结束(会返回拖拽的当前元素信息及丢弃(放置)到指定位置的元素信息,可能为null)
}}>
{children}
<DragOverlay>
// 自定义的标识 draggingId - 当前正在被拖拽的元素id
{draggingId ? (
<div
style={{
// 被拖拽元素样式
}}></div>
) : null}
</DragOverlay>
<DndContext>
碰撞算法
collisionDetection自定义碰撞算法,dndkit会提供一些数据,用户可以在数据基础上进行处理
const customCollisionDetectionStrategy = (rects) => {
/**
* active 当前拖拽元素及其data
* collisionRect 碰撞元素data
* pointerCoordinates 当前指针坐标
* droppableContainers 所有dropabble对象->arr
data: {current: {…}}
id: ""
key: "Droppable-0", // dndkit给对象增加的字段,可用于排序,数值越大代表当前元素嵌套最深(最上层)
node: {current: '当前元素'}
rect: {current: bottom: 0, height: 96, left: 0, right: 0, top: 0, width: 1920}
*/
const { active, collisionRect, pointerCoordinates, droppableContainers } = rects;
// ... 数据处理,需返回碰撞到的元素数组(进行排序)第一个为当前碰撞到的元素
return arr;
}
传感器
const sensors = useSensors(useSensor(MouseSensor));
// MouseSensor dndkit提供的传感器,默认是使用所有传感器,我这里只使用了mouse传感器,碰撞检测返回的数据可能和当前传感器有关联?我这里没做尝试,但碰撞算法确实是依托于鼠标位置做的处理
使用drag或drop时可带额外参数
在使用别的拖拽组件时,很多数据处理会很麻烦,dndkit提供了data方式,可以在所有方法里或碰撞算法里返回这些data,方便数据处理
// drag初始化 drop也一样,官方文档里有
const { attributes, listeners, setNodeRef } = useDraggable({
id: dragId,
disabled: isDragDisabled, // 是否允许拖拽
data: { // 自定义参数,需要的数据放这里
...otherProps,
},
});
// 赋值拖拽过程中的位移样式, 使用dragOverlay则不赋值style
// const style = {
// transform: CSS.Translate.toString(transform),
// };
<div
ref={setNodeRef}
// dragOverly 使用时,不给当前元素赋值
// style={style}
{...listeners}
{...attributes}></div>
dragOverly
使用dragOverly相当于不更改原对象,当拖拽时会复制一个新的div(记得将被拖拽的元素的样式赋值给dragOverly)
拖拽还可以与resize兼容使用,自己动手尝试一下吧~
以上都为自己使用过程中用到的方法,还有很多场景或方式没有尝试,但dndkit可以适用于更多的场景和方式,真的值得尝试,yyds
以上如果有错误的地方,欢迎指正~~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。