import { Meta } from '@storybook/blocks'
import treeStories from './dnd-tree.stories'
Context
ONESDndContext
直接从 @dnd/core
中导出
import { DndContext } from '@dnd/core'
export { ONESDndContext }
TreeDndContext
树形结构拖拽上下文,包含拖拽指示线以及拖拽事件的处理,必须在 ONESDndContext
中使用
- 处理树结构拖拽事件,计算并注入
dropPosition
- 计算
activeData
、initialActiveNodeRect
、initialCoordinates
等参数(虚拟滚动支持)
@dnd/core
在虚拟滚动时会丢失数据,需要做额外保存(TODO:这个逻辑应该是公共逻辑,现在暂时放在 TreeDndContext 中处理了)
<ONESDndContext draggable={isDraggable}>
<TreeDndContext<DndNodeItem>
onDragStart={onNodeDragStart}
onDragEnd={onNodeDragEnd}
onDragEnter={onNodeDragEnter}
onDragLeave={onNodeDragLeave}
onDragOver={onNodeDragOver}
onDrop={onNodeDrop}
>
{children}
</TreeDndContext>
</ONESDndContext>
事件
export interface DragEventInfo<T = AnyData, N extends string = ''> {
name: N
key: React.Key
node: T
dragNode: T
active: Active
nativeEvent: Event
}
hooks
useDndItem
创建一个拖拽/放置元素,必须在 ONESDndContext
中使用
参数:
- id 必传,唯一标识
- data 可以传递任意数据,用于渲染
DragOverlay
、影响事件回调参数等 - disabled 是否禁用拖拽(依然可放置)
返回值:
- setNodeRef 用于绑定拖拽元素的 ref
- isDragging 当前元素是否正在拖拽
- isOver 当前元素是否正在被拖拽元素覆盖
- listeners 需要绑定在拖拽元素上的事件(*)
- attributes 需要绑定在拖拽元素上的属性(*)
const { setNodeRef, isDragging, isOver, listeners, attributes } = useDndItem({
id: nodeKey,
data: {
key: nodeKey,
content,
},
})
return (
<div className="dnd-item" ref={setNodeRef} {...listeners} {...attributes}></div>
)
useTreeDndContext
可以获取到目前的拖拽上下文
export function useTreeDndContext() {
const dndKitContext = useDndContext()
const TreeDndContext = React.useContext(Context)
return {
...dndKitContext,
...TreeDndContext,
}
}
modifiers
@ones-design/dnd
内置了一些拖拽修饰器,用于调整拖拽节点的位置
export declare type Modifier = (args: {
activatorEvent: Event | null
active: Active | null
activeNodeRect: ClientRect | null
draggingNodeRect: ClientRect | null
containerNodeRect: ClientRect | null
over: Over | null
overlayNodeRect: ClientRect | null
scrollableAncestors: Element[]
scrollableAncestorRects: ClientRect[]
transform: Transform
windowRect: ClientRect | null
}) => Transform
useMouseFollowModifier
被拖拽元素跟随鼠标移动,目前应用在 @ones-design/tree
上
TODO::这个 modifier 实际和树拖拽没有绑定关系,只是现在的实现依赖 TreeContext,因为目前没有一个 BaseContext 来导出坐标等数据
const mouseFollowModifier = useMouseFollowModifier()
<DragOverlay modifires={[mouseFollowModifier]}/>
useVerticalRestrictModifier
被拖拽元素只能在垂直方向移动,目前应用在 @ones-design/table
上
const verticalRestrictModifier = useVerticalRestrictModifier()
<DragOverlay modifires={[verticalRestrictModifier]}/>