HTML 拖放
上一课 Geolocation 在授权后请求坐标。本课离开坐标,介绍 HTML 拖放:标记可拖内容、用 dataTransfer 携带小载荷,并决定放下时做什么。范围务实——draggable、dragover 上的 preventDefault、移动或贴标签——不是 sortable 库或上传应用课。
为何在 HTML 课学拖放
初学者常想把卡片拖进盒子。原生 DnD 是常见的第一套 API。在 Geolocation 之后,分工不同:HTML 标记源;JS 拥有事件与 drop 含义。
直接回答
1) draggable="true"。2) 在 dragstart 中 setData。3) 在 dragover 上 preventDefault。4) 在 drop 中 getData 并改 DOM/UI。5) 没有特殊 dropzone 标签。6) 若重要,提供按钮/键盘路径。
📊 dragstart vs dragover vs drop
| Topic | dragstart | dragover | drop |
|---|---|---|---|
| Typical role | Start drag; set dataTransfer | Allow drop (preventDefault) | Apply the result |
| Runs on | Draggable source | Potential target (often) | Drop target |
| Must preventDefault? | Usually no | Yes — so drop can fire | Yes — avoid default navigation quirks |
| Beginner payload | setData("text/plain", id) | — | getData + move/label |
| This course depth | Required | Required | Required (simple move/label) |
微型移入区域演示
蓝色框可拖;放下后进入虚线区。若 dragover 不 preventDefault,drop 常不触发。
<div id="item" draggable="true" style="padding:8px;background:#cdf;width:120px;">Drag me</div>
<div id="zone" style="margin-top:12px;padding:24px;border:2px dashed #666;">Drop here</div>
<script>
const item = document.getElementById("item");
const zone = document.getElementById("zone");
item.addEventListener("dragstart", function (e) {
e.dataTransfer.setData("text/plain", "item");
});
zone.addEventListener("dragover", function (e) {
e.preventDefault();
});
zone.addEventListener("drop", function (e) {
e.preventDefault();
zone.appendChild(item);
});
</script>
阅读移动调用
- draggable 启动手势
- dragstart 设置 dataTransfer
- dragover + preventDefault 允许放下
- drop 改变 DOM
- 与 Geolocation 不同:无设备坐标
- 保持演示精简
dataTransfer 载荷演示
有时不移动同一节点——携带文本并在放下时显示,多个源共享一个目标时很有用。
<p id="a" draggable="true" style="display:inline-block;padding:6px;background:#fec;margin-right:8px;">Alpha</p>
<p id="b" draggable="true" style="display:inline-block;padding:6px;background:#cfe;margin-right:8px;">Beta</p>
<div id="tray" style="margin-top:12px;padding:16px;border:2px dashed #444;">Drop a label here</div>
<pre id="note"></pre>
<script>
const tray = document.getElementById("tray");
const note = document.getElementById("note");
function arm(id, label) {
document.getElementById(id).addEventListener("dragstart", function (e) {
e.dataTransfer.setData("text/plain", label);
});
}
arm("a", "Alpha");
arm("b", "Beta");
tray.addEventListener("dragover", function (e) {
e.preventDefault();
});
tray.addEventListener("drop", function (e) {
e.preventDefault();
note.textContent = "Dropped: " + e.dataTransfer.getData("text/plain");
});
</script>
阅读 dataTransfer 思路
- setData/getData 传递短字符串
- text/plain 适合初学者
- 多源一目标
- 不是上传产品
- 不是 Geolocation
- 下一课:web workers
何时使用 DnD
- 卡片拖入明确区域:适合入门
- 无替代的关键操作:不好
- 保存主题:Web Storage
- GPS:是 Geolocation
- 完整看板产品:超出本入门
练习 — 拖、放、贴标签
- 试移动演示。
- 暂时去掉 preventDefault 观察 drop 失败。
- 试 dataTransfer 演示。
- (可选)无拖动的按钮。
- 一句话:Geolocation 读坐标;DnD 用指针移动/贴标签。
- 优先真实浏览器窗口。
- 预告:web workers。
易错点
- 忘记 dragover 上的 preventDefault
- 仅 DnD 界面无替代
- 期待 dropzone 标签
- 与 Geolocation 混淆
- 滥用 DnD 而非按钮
- 把入门当成完整 sortable 课
小结
- DnD 使用 draggable、dataTransfer 与三个事件
- dragover 上的 preventDefault 常必需
- HTML 标记源;脚本定义 drop
- 需要时提供非拖动路径
- Geolocation 是获准坐标;本课是指针移动/贴标签
- 下一课:web workers
🧠 测试您的知识
测试您的知识
通过这个互动测验挑战自己,看看你对这个主题的理解程度如何
📝 说明
- 仔细阅读每个问题
- 为每个问题选择最佳答案
- 您可以随时重新参加测验
- 您的进度将显示在顶部