
pragmatic-drag-androp-hitbox 如何用 list item hitbox 判断 reorder-before、reorder-after 与 combine 操作【免费下载链接】pragmatic-drag-and-dropFast drag and drop for any experience on any tech stack项目地址: https://gitcode.com/GitHub_Trending/pr/pragmatic-drag-and-drop在实现列表拖拽时你经常需要在拖动过程中判断指针当前悬停在某个列表项的哪个区域从而决定应该执行哪种操作把被拖项排到目标项之前reorder-before、排到目标项之后reorder-after还是合并到目标项上combine。atlaskit/pragmatic-drag-and-drop-hitbox包中的 list item hitbox 就是为这件事设计的它在 drop target 上自动划分命中区域并根据你声明了哪些操作可用实时计算指针位置对应的操作。该包依赖核心包atlaskit/pragmatic-drag-and-drop且不依赖任何视图库如react或 Atlassian Design System见 packages/hitbox/constellation/index/about.mdx。本文基于仓库中的文档与实现代码说明如何挂载、判断并验证这些操作。准备导入 attachInstruction 与 extractInstructionlist item hitbox 提供两个函数都从atlaskit/pragmatic-drag-and-drop-hitbox/list-item导入包的实际入口定义见 packages/hitbox/package.json 的exports字段attachInstruction在 drop target 的getData中把计算出的操作指令附加到你的数据对象上extractInstruction在拖拽事件如onDrop中从数据对象里取出指令。指令的类型定义如下文档中的类型见 about.mdxtype Operation reorder-before | reorder-after | combine; // an Instruction contains the applied operation, and whether the operation was blocked. type Instruction { // What the operation is operation: Operation; // whether or not the operation was blocked blocked: boolean; };源码中的Instruction实际还包含axis字段horizontal | vertical记录该 drop target 使用的轴向见 packages/hitbox/src/list-item.ts。每个操作都有三个可用性取值默认值是not-availablenot-available默认availableblocked类似available但一般用于显示警告色在 drop target 上挂载操作判断挂载的核心是在dropTargetForElements的getData回调中调用attachInstruction。文档给出的完整用法import { attachInstruction, extractInstruction, type Instruction, } from atlaskit/pragmatic-drag-and-drop-hitbox/list-item; dropTargetForElements({ element: myElement, getData: ({ input, element }) { // your base data you want to attach to the drop target const data { itemId: A, }; // this will attach the closest edge to your data object return attachInstruction(data, { input, element, operations: { reorder-before: available, reorder-after: available, combine: available, }, }); }, onDrop: (args) { const instruction: Instruction | null extractInstruction(args.self.data); }, });这里有两个关键点getData在拖拽过程中会被反复调用每次指针移动都会触发因此attachInstruction会基于最新的input.clientX/input.clientY与元素getBoundingClientRect()重新计算操作命中的区域随指针位置实时变化。operations中每一项都是可选的缺省即为not-available。你只声明需要的操作hitbox 会自动按可用操作的组合调整区域划分不需要你自己算比例。hitbox 如何划分列表项区域划分完全由你声明了哪些操作决定。文档about.mdx 的 “Behaviour” 一节给出了每种组合对应的划分规则以纵向列表axis默认vertical为例三种操作全部 available指针位置命中操作元素起始边之外before start edgereorder-before前 1/4reorder-before中间 1/2combine后 1/4reorder-after结束边之外after end edgereorder-after仅reorder-before和reorder-afteravailable指针位置命中操作起始边之外reorder-before前 1/2reorder-before后 1/2reorder-after结束边之外reorder-after仅reorder-before和combineavailable指针位置命中操作起始边之外reorder-before前 1/4reorder-before中间 3/4combine结束边之外combine仅reorder-after和combineavailable指针位置命中操作起始边之外combine前 3/4combine后 1/4reorder-after结束边之外combine只有单一操作 available例如combine元素内外全部区域都命中该操作。没有任何 available或 blocked操作任何位置取出的Instruction都是null。实现代码印证了这些规则并且明确了两处“边界归属”偏好见 packages/hitbox/src/attach-instruction-2.ts同时只有两个 reorder 操作时以元素中点划分指针恰在中点上时返回reorder-after即“slight preference to moving forward”存在combine时前 1/4 的边界线归reorder-before后 1/4 的边界线归reorder-after即“slight preference to reordering”——指针正好压在 1/4 分界线上时优先命中 reorder 而不是 combine。如何禁用与拦截操作禁用not-available不想让某个操作出现时把它设为not-available或者直接不写默认值就是not-available。hitbox 会自动按剩余操作重新划分区域return attachInstruction(data, { input, element, operations: { reorder-before: available, reorder-after: not-available, // reordering after no longer available }, });拦截blocked当某个操作“此刻”不允许、但将来可能允许时文档举的例子是 Confluence 的草稿页面不能作为拖放目标用blocked显式告诉用户该操作当前不可执行。blocked 不影响区域划分只会在结果中把blocked置为true供 drop indicator 显示警告色return attachInstruction(data, { input, element, operations: { combine: blocked, }, });取出判断结果在拖拽事件中用extractInstruction取出指令返回值是Instruction | nullonDrop: (args) { const instruction: Instruction | null extractInstruction(args.self.data); // instruction null 说明该 target 上没有任何可用的操作 // instruction.operation 是 reorder-before | reorder-after | combine // instruction.blocked 指示该操作当前是否被拦截 },源码注释中还给出了在 monitor 中读取的典型写法见 packages/hitbox/src/extract-instruction-2.tsmonitorForElements({ onDrop({ location }) { const innerMost location.current.dropTargets[0]; if (!innerMost) { return; } const instruction: Instruction | null extractInstruction(innerMost.data); }, });两种取法取的是同一份数据getData里附加了什么事件回调里就能从 drop target 的data上取什么。所有操作都不可用时attachInstruction不附加任何指令extractInstruction返回null此时应自行处理“无处可放”的分支。横向列表与树结构横向列表attachInstruction需要知道列表的方向通过axis参数指定默认vertical横向列表传horizontalreturn attachInstruction(data, { input, element, axis: horizontal, // vertical is the default operations: { reorder-before: available, reorder-after: available, }, });树结构可选分支list item hitbox 可以直接用于树——把树的每一层当作一个独立的“list”处理。文档给出的两条规则可以按各节点需要自由启用操作对于已展开expanded的树节点不要允许reorder-after操作。验证用仓库的单元测试核对边界行为如果你不确定某个指针位置会命中哪个操作仓库自带的单元测试是最直接的核对依据packages/hitbox/tests/unit/list-item.spec.ts 用一个固定的矩形top/left 为 10right/bottom 为 100构造了 12 个典型位置起始边之外、起始边、1/4 线前后、中心点、3/4 线前后、结束边、结束边之外并针对每种操作组合仅 reorder-before、仅 reorder-after、仅 combine、双 reorder、全部可用、reordercombine 的各种组合、全部不可用在vertical与horizontal两个轴向下断言了期望的operation值例如全部操作 available 时中心点命中combine恰在 1/4 分界线上命中reorder-before恰在 3/4 分界线上命中reorder-after仅双 reorder available 时中心点命中reorder-after全部操作not-available时任何位置extractInstruction都返回nullblocked 的操作组合下区域划分与 available 相同只是blocked字段为true。你自己的实现可以在同样的位置取样点元素 1/4、中点、3/4 分界线及其前后 1 像素对照该期望表检查extractInstruction的返回值是否与文档的划分规则一致。命中操作之后执行 reorder文档明确说明list item hitbox 本身不提供执行状态更新的具体工具因为combine这类操作需要你自行决定状态如何变化对于reorder-before和reorder-after可以直接使用核心包的reorder工具见 packages/documentation/constellation/05-core-package/05-utilities/index.mdximport { reorder } from atlaskit/pragmatic-drag-and-drop/reorder; const reordered reorder({ list: [A, B, C], startIndex: 0, finishIndex: 1, }); console.log(reordered); // [B, A, C]reorder返回重排后的新数组不修改原数组。边界与限制axis只有vertical默认和horizontal两个取值列表方向必须与 UI 实际方向一致否则区域划分会算错轴。区域比例1/4、1/2、3/4由 hitbox 内部计算attachInstruction不暴露参数用于调整这些比例能控制区域的唯一方式是改变operations中各项的available/not-available/blocked状态。判断发生在 drop target 一侧getData被拖元素本身不提供指令如果你用的是 monitor 的onDrop记得从location.current.dropTargets的 target 数据上提取而不是从拖拽输入上提取。旧版的tree-itemhitboxreorder-above/reorder-below/make-child/reparent文档已标记为请使用 list item hitbox 替代新代码应使用本文的 list item 入口。【免费下载链接】pragmatic-drag-and-dropFast drag and drop for any experience on any tech stack项目地址: https://gitcode.com/GitHub_Trending/pr/pragmatic-drag-and-drop创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考