实现拖放与可排序接口Skill implementing-drag-drop

这个技能用于通过React和TypeScript实现拖放和可排序功能,适用于看板、列表排序、文件上传等场景,注重无障碍性、触摸支持和性能优化,关键词包括:拖放、React、TypeScript、前端开发、UI交互、可排序、看板、文件上传。

前端开发 0 次安装 0 次浏览 更新于 3/23/2026

name: 实现拖放功能 描述: 使用React/TypeScript实现拖放和可排序接口,包括看板、可排序列表、文件上传和可重排序网格。适用于需要直接操作、空间组织或触摸友好重排序的交互式UI。

拖放与可排序接口

目的

这个技能帮助使用现代React/TypeScript库实现拖放交互和可排序接口。它涵盖无障碍优先方法、触摸支持和性能优化,用于创建直观的直接操作UI。

何时使用

调用此技能当:

  • 构建Trello风格的看板,带有可拖动的卡片在列之间
  • 创建带有拖动手柄的可排序列表用于优先级排序
  • 实现带有视觉拖放反馈的文件上传区域
  • 构建可重排序的网格用于仪表板小部件或图库
  • 创建具有基于节点接口的可视化构建器
  • 实现任何需要通过直接操作进行空间重组的UI

核心模式

可排序列表

参考 references/dnd-patterns.md 用于:

  • 带有拖动手柄的垂直列表
  • 用于选项卡/轮播重排序的水平列表
  • 带有2D拖动的网格布局
  • 边缘附近的自动滚动

看板

参考 references/kanban-implementation.md 用于:

  • 带有卡片的的多列看板
  • WIP限制和泳道
  • 悬停时的卡片预览
  • 列管理(添加/删除/折叠)

文件上传区域

参考 references/file-dropzone.md 用于:

  • 视觉反馈状态
  • 文件类型验证
  • 多文件处理
  • 进度指示器

无障碍性

参考 references/accessibility-dnd.md 用于:

  • 键盘导航模式
  • 屏幕阅读器公告
  • 替代UI方法
  • ARIA属性

库选择

主要: dnd-kit

现代、无障碍且高性能的React拖放库。

参考 references/library-guide.md 用于:

  • 库比较(dnd-kit vs 替代品)
  • 安装和设置
  • 核心概念和API
  • 从react-beautiful-dnd迁移

关键特性

  • 内置无障碍支持
  • 触摸、鼠标和键盘输入
  • 零依赖(~10KB核心)
  • 高度可定制
  • TypeScript原生

实施工作流

步骤1: 分析需求

确定所需的拖放模式:

  • 简单列表重排序 → 可排序列表模式
  • 多容器移动 → 看板模式
  • 文件处理 → 拖放区域模式
  • 复杂交互 → 可视化构建器模式

步骤2: 设置库

安装所需包:

npm install @dnd-kit/core @dnd-kit/sortable @dnd-kit/utilities

步骤3: 实现核心功能

使用示例作为起点:

  • examples/sortable-list.tsx 用于基本列表
  • examples/kanban-board.tsx 用于多列看板
  • examples/file-dropzone.tsx 用于文件上传
  • examples/grid-reorder.tsx 用于网格布局

步骤4: 添加无障碍性

参考 references/accessibility-dnd.md 以:

  • 实现键盘导航
  • 添加屏幕阅读器公告
  • 提供替代控制
  • 用辅助技术测试

运行 scripts/validate_accessibility.js 检查实施。

步骤5: 优化性能

对于超过100项的列表:

  • 参考 references/performance-optimization.md
  • 实现虚拟滚动
  • 使用 scripts/calculate_drop_position.js 进行高效计算

步骤6: 使用设计令牌进行样式

应用主题使用design-tokens技能:

  • 参考设计令牌变量
  • 实施拖放状态(悬停、拖动、放下)
  • 添加视觉反馈和动画

移动与触摸支持

参考 references/touch-support.md 用于:

  • 长按以启动拖动
  • 防止拖动期间滚动
  • 触摸友好的点击区域(最小44px)
  • 手势冲突解决

状态管理

参考 references/state-management.md 用于:

  • 在React中管理拖放状态
  • 乐观更新
  • 撤销/重做功能
  • 持久化顺序更改

脚本

计算放下位置

运行 scripts/calculate_drop_position.js 以:

  • 确定有效的放下区域
  • 计算插入索引
  • 处理边缘情况

生成配置

运行 scripts/generate_dnd_config.js 以:

  • 创建dnd-kit配置
  • 设置传感器和修饰器
  • 配置动画

验证无障碍性

运行 scripts/validate_accessibility.js 以:

  • 检查键盘导航
  • 验证ARIA属性
  • 测试屏幕阅读器兼容性

示例

每个示例包括完整的TypeScript代码和无障碍性:

可排序列表

examples/sortable-list.tsx

  • 带有拖动手柄的垂直列表
  • 键盘导航(空格/回车抓取,箭头移动)
  • 屏幕阅读器公告

看板

examples/kanban-board.tsx

  • 带有可拖动卡片的的多列
  • 卡片在列之间的移动
  • 列管理功能
  • WIP限制

文件拖放区域

examples/file-dropzone.tsx

  • 拖放文件以上传
  • 视觉反馈状态
  • 文件类型验证
  • 上传进度

网格重排序

examples/grid-reorder.tsx

  • 2D网格拖动
  • 放下时的自动布局
  • 响应式断点

资产

TypeScript类型

assets/drag-state-types.ts 提供:

  • 拖放状态的类型定义
  • 事件处理程序类型
  • 配置接口

配置模式

assets/dnd-config-schema.json 定义:

  • 有效配置选项
  • 传感器设置
  • 动画参数

最佳实践

视觉反馈

  • 显示拖动手柄(⋮⋮)以指示可拖动性
  • 更改光标(抓取 → 抓取中)
  • 显示放下区域占位符
  • 使拖动项目半透明
  • 高亮有效的放下目标

性能

  • 使用CSS变换,而不是位置属性
  • 应用 will-change: transform 用于动画
  • 节流拖动事件用于大列表
  • 需要时实现虚拟滚动

无障碍优先

  • 始终提供键盘替代方案
  • 包括屏幕阅读器公告
  • 用NVDA/JAWS/VoiceOver测试
  • 提供非拖动替代方案(按钮/表单)

错误处理

  • 显示无效放下反馈
  • 实现撤销功能
  • 成功放下后自动保存
  • 优雅处理网络故障

常见陷阱

避免这些问题

  • 忘记键盘导航
  • 缺失触摸支持
  • 不防止拖动期间滚动
  • 忽略无障碍性
  • 大列表性能差

解决方案

参考适当指南用于每个问题:

  • 无障碍性 → references/accessibility-dnd.md
  • 触摸 → references/touch-support.md
  • 性能 → references/performance-optimization.md
  • 状态 → references/state-management.md

测试清单

部署前,验证:

  • [ ] 键盘导航完全工作
  • [ ] 屏幕阅读器公告所有操作
  • [ ] 触摸设备可以平滑拖动
  • [ ] 性能可接受与预期数据量
  • [ ] 视觉反馈清晰且响应
  • [ ] 撤销/重做功能工作
  • [ ] 为无障碍性提供替代UI
  • [ ] 在所有目标浏览器中工作

下一步

实施基本拖放后:

  1. 添加高级功能(自动滚动、多选)
  2. 为移动设备实现手势支持
  3. 用Framer Motion添加动画抛光
  4. 创建自定义拖动预览组件
  5. 构建复杂交互(嵌套拖动)