dragover 和 drop 事件
定义有效的放置目标并处理 drop 事件
dragover 和 drop 事件 是 CoddyKit 上的免费 HTML Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 HTML Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 HTML Academy 课程共包含 4 节课。
放置目标需要两个处理程序
放置目标必须同时处理 dragover(允许放置)和 drop(接收内容)。如果没有处理拖拽经过事件,浏览器会拒绝触发放置事件,因为默认行为是“不存在任何放置目标元素”。
必须调用 preventDefault
在拖拽经过处理程序中必须调用 e.preventDefault()。这会取消浏览器拒绝放置的默认行为。没有它,光标会一直显示为“不允许”,放置事件也永远不会触发,无论用户如何操作。
zone.addEventListener("dragover", (e) => {
e.preventDefault();
});
zone.addEventListener("drop", (e) => {
e.preventDefault();
console.log(e.dataTransfer.getData("text/plain"));
});拖入与拖离事件
光标进入目标时,拖入事件会触发一次;离开时,拖离事件会触发一次。可以使用它们切换视觉上的“拖拽经过”高亮:进入时添加一个类,离开时移除该类,让用户看到哪个区域将接收放置内容。
拖离事件会因子元素触发
有一个容易忽略的特性:将光标移到子元素上时,会先在父元素上触发拖离事件,然后在子元素上触发拖入事件。请在拖入事件中递增计数器,在拖离事件中递减计数器,只有当计数器回到零时才移除高亮。
let counter = 0;
zone.addEventListener("dragenter", () => {
counter++;
zone.classList.add("over");
});
zone.addEventListener("dragleave", () => {
counter--;
if (counter === 0) zone.classList.remove("over");
});设置 dropEffect
在拖拽经过事件中设置 e.dataTransfer.dropEffect = "move"(或复制、链接、无),即可控制光标并告知源元素将发生什么。该效果必须与源元素的 effectAllowed 兼容,否则放置会被拒绝。
在放置时读取数据
在放置处理程序中调用 e.dataTransfer.getData(format),并传入与 setData 使用的相同 MIME 类型(通常是纯文本类型)。然后通过标识符定位元素,将其追加到目标中,更新数据模型,或执行应用程序所需的其他操作。
在放置时阻止默认行为
还需要在放置处理程序中调用 e.preventDefault()。否则浏览器会退回到原生行为——对于放置的 URL,这意味着跳转到该链接,从而立即丢失页面状态。
从桌面拖入内容
浏览器会将从 OS 拖入的文件转换为放置事件,并填充 e.dataTransfer.files。遍历 FileList,并使用文件接口读取每个文件,即可支持图像上传、log 文件查看器或文档导入器。
zone.addEventListener("drop", (e) => {
e.preventDefault();
for (const file of e.dataTransfer.files) {
console.log(file.name, file.size);
}
});dataTransfer 中的多种类型
setData 可以将同一载荷存储为多种 MIME 类型:纯文本用于回退,统一资源标识符列表用于 URL,JSON 用于结构化载荷。放置目标会通过 getData 选择它能够理解的最丰富类型。
与触摸事件协调
移动浏览器不会根据触摸操作自动合成拖拽经过和放置事件。为了提供统一体验,请使用指针事件配合手动命中检测,或使用能够抽象这些差异的库。原生网页拖放最好视为仅适用于桌面设备。
性能提示
拖拽经过事件会在光标移动时持续触发,通常每秒几十次。请让处理程序保持轻量:不要在其中执行耗时的 DOM 查询或布局读取。可以在拖入事件中缓存矩形区域,并在光标停留于目标上时重复使用。
知识检查
为什么在拖拽经过处理程序中调用 e.preventDefault() 之前,目标上的放置事件永远不会触发?
总结
一个正常工作的放置目标会监听拖拽经过事件(始终调用 preventDefault,可选择设置 dropEffect)和放置事件(再次调用 preventDefault,然后读取 dataTransfer.getData 或 dataTransfer.files)。使用拖入/拖离事件配合计数器显示高亮,并让处理程序保持轻量,因为拖拽经过事件触发得非常频繁。
常见问题解答
「dragover 和 drop 事件」课时是免费的吗?
是的 — 「dragover 和 drop 事件」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 HTML Academy 课程的其余内容,请升级到 CoddyKit PRO。 HTML Academy 课程共包含 4 节课。
「dragover 和 drop 事件」这节课中我会学到什么?
定义有效的放置目标并处理 drop 事件 你通过在浏览器中直接运行的动手代码来练习 HTML Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 HTML Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 HTML Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「dragover 和 drop 事件」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 HTML Academy 课中编写并运行代码吗?
能。每节 HTML Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- draggable 属性与 dragstart 事件
- dragover 和 drop 事件
- dataTransfer 对象
- 实用的拖放排序列表