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
- [ ] 在所有目标浏览器中工作
下一步
实施基本拖放后:
- 添加高级功能(自动滚动、多选)
- 为移动设备实现手势支持
- 用Framer Motion添加动画抛光
- 创建自定义拖动预览组件
- 构建复杂交互(嵌套拖动)