设了 draggable="true" 却拖不动、放不下、没数据,根本原因是事件链断在三个环节:dragstart 未调用 dataTransfer.setData()、dragover 未每次调用 preventDefault()、目标元素无尺寸或被样式拦截。

设了 draggable="true" 却拖不动、放不下、没数据——不是属性写错了,是事件链断在了三个硬性环节上:没调 dataTransfer.setData()、没拦 dragover 的默认行为、目标元素没尺寸或被样式拦住。
dragstart 里必须调用 dataTransfer.setData()
浏览器只把 draggable="true" 当作“允许被抓取”的标记,真正启动拖拽流程的开关是 dataTransfer.setData()。漏掉这行,光标可能变手形,但后续所有事件(包括 drop)都不会触发。
-
type参数必须用标准 MIME 类型:'text/plain'最稳;'Text'、'mydata'在 Firefox 中静默失败 - 哪怕只传一个 ID,也得显式写:
e.dataTransfer.setData('text/plain', e.target.id) - 想传对象?先
JSON.stringify()再塞进去:e.dataTransfer.setData('text/plain', JSON.stringify({id: 't1', type: 'task'})) - 不能提前设、不能在别的事件里设——
dataTransfer对象只在dragstart回调中可写
dragover 必须每次调 e.preventDefault()
drop 能否触发,完全取决于 dragover 是否被阻止默认行为。这不是“进区域时拦一次就行”,而是鼠标每移动一帧,只要还在目标上,就必须调一次 e.preventDefault()。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
- 只监听
drop没用;只在dragenter里preventDefault()也没用 -
e.stopPropagation()或return false都不能替代e.preventDefault() - 目标是空
<div id="dropzone"></div>?加min-height: 24px或padding: 4px,否则根本派发不出dragover - Safari 更严格:建议在
dragover回调里补一句e.dataTransfer.dropEffect = 'move'
哪些地方写 draggable="true" 是无效的
这个属性不继承、不穿透、不妥协。写错位置或套错标签,等于没写。
立即学习“前端免费学习笔记(深入)”;
- 别加在父容器上:
<div class="list" draggable="true"><div>item</div></div>—— 子元素不会继承 -
<input>和<textarea>上硬加draggable="true"会被浏览器强制忽略,这是渲染层限制 -
<template>里的draggable="true"不生效——内容未挂载到 DOM,事件根本不会绑定 - 元素没尺寸(比如空
<div draggable="true"></div>且没width/height/padding),dragstart不触发 -
user-select: none或pointer-events: none会直接拦住dragstart,连光标都不变
最易被忽略的点:移动端原生 draggable 完全不可用。iOS Safari 和 Android Chrome 均不触发 dragstart、drop 等任何事件——这不是代码能修的,是规范层面缺失。如果业务必须支持触摸拖拽,得降级为 touchstart/touchmove + CSS transform 手动模拟,或引入 interact.js 这类已做平台适配的库。


















