彻底掌握原生 HTML5 拖拽 API:从基础到列表排序实战

83 阅读2分钟

在前端开发中,拖拽(Drag and Drop)是一个非常常见的交互需求。虽然现在有很多优秀的第三方库(如 vuedraggable, dnd-kit),但了解原生 HTML5 Drag and Drop API 依然是进阶高级前端的必经之路。

本文将带你深入浅出地了解原生拖拽 API,并提供一个完整的实战示例。

1. 核心概念:谁是“源”,谁是“目的”?

原生拖拽涉及两个主体:

  1. 被拖拽元素(Drag Source) :你想移动的那个东西。
  2. 放置目标(Drop Target) :你想把东西放进去的区域。

关键属性:draggable

要让一个元素可以被拖拽,必须给它加上 draggable="true" 属性(图片和链接默认就是可拖拽的)。

<div draggable="true">抓起我!</div>

2. 核心事件流

触发在“被拖拽元素”上的事件:

  • dragstart: 用户开始拖拽时触发(通常在这里设置数据)。
  • drag: 拖拽过程中持续触发。
  • dragend: 拖拽结束时触发(无论成功与否)。

触发在“放置目标”上的事件:

  • dragenter: 拖拽元素进入目标范围。
  • dragover: 在目标上方移动时触发(必须在这里调用 e.preventDefault() 才能允许放置)。
  • dragleave: 离开目标范围。
  • drop: 在目标上松开鼠标(放置动作完成)。

3. DataTransfer 对象:数据的搬运工

DataTransfer 对象是拖拽 API 的灵魂,用于在源和目标之间传递数据。

  • event.dataTransfer.setData(format, data): 保存数据。
  • event.dataTransfer.getData(format): 读取数据。

4. 为什么 dragover 要取消默认行为?

这是初学者最容易踩的坑。浏览器默认是不允许在元素上放置任何内容的。 为了启用 drop 事件,你必须dragover 事件中阻止默认行为:

dropZone.addEventListener('dragover', (e) => {
  e.preventDefault(); // 关键!否则 drop 事件不会触发
});

5. 实战:任务看板拖拽

下面是一个简单的 Kanban 看板效果,支持在“待处理”和“已完成”两个列表之间相互拖拽。

(请参考下方的演示代码文件获取完整实现)

6. 总结与建议

原生 API 的优点是零依赖、性能好,但在处理复杂逻辑(如动画、跨浏览器兼容性、嵌套拖拽)时较为繁琐。