原生拖拽API生效需同时满足三个硬性条件:①源元素设draggable="true";②绑定dragstart事件并调用dataTransfer.setData()设数据;③目标区域在dragover事件中必须调用event.preventDefault(),缺一即静默失败。

原生拖拽 API 能用,但必须满足三个硬性条件:draggable="true"、dragstart 中调用 dataTransfer.setData()、目标区域的 dragover 里执行 event.preventDefault()。漏掉任意一个,拖拽就静默失败——鼠标能抓起,松手没反应,控制台还不报错。
为什么 draggable="true" 加了却没反应?
这是最常卡住人的第一步。draggable="true" 只是“允许拖”,不是“自动拖”。浏览器根本不会替你注册事件或传数据。
-
dragstart必须显式绑定,用addEventListener('dragstart', ...)或内联ondragstart,否则事件压根不触发 - 空
<div> 没宽高,浏览器判定“不可交互”,<code>dragstart直接跳过——加min-height: 24px或padding: 8px就行 -
user-select: none或pointer-events: none会拦截 mousedown,拖拽链路直接断在起点 -
<input>和<textarea></textarea>即使设了draggable="true"也无效,浏览器强制禁用 - 只监听
drop不够,dragover必须存在且调用e.preventDefault()——e.stopPropagation()或return false都不行 - 目标容器如果是空
<div>,还要确认没被 <code>display: none或visibility: hidden隐藏 - Safari 对
effectAllowed和dropEffect匹配更敏感:建议在dragstart里设e.dataTransfer.effectAllowed = 'move',在dragover里设e.dataTransfer.dropEffect = 'move' -
drop事件里必须先调用event.preventDefault(),否则浏览器会按默认行为打开文件(比如图片直接在新页显示) -
event.dataTransfer.files是只读的 FileList,不能直接 push 或 splice;遍历时要用for (let i = 0; i ,别用 <code>for...of(部分老版本 Safari 不支持) - 检查
files[i].type.startsWith('image/')比files[i].name.endsWith('.jpg')更可靠,后者容易被伪造 - 移动端完全不支持原生拖拽 API,iOS Safari 和多数 Android WebView 中
dragstart基本不触发——必须保留<input type="file">作为降级方案
drop 事件死活不触发?先查 dragover
90% 的“拖到目标上没反应”问题,根源都在 dragover。浏览器默认禁止任何区域接收拖放,preventDefault() 是唯一开关。
文件拖入上传时 dataTransfer.files 为空?
这不是 API 失效,而是事件处理顺序或类型判断出了问题。
立即学习“前端免费学习笔记(深入)”;
真正难的不是写对那几行代码,而是理解拖拽生命周期里每个事件的职责边界:dragstart 负责“发车”,dragover 负责“开闸”,drop 负责“卸货”。跨 iframe 时数据只能序列化传递,Safari 对 effectAllowed 更较真,而移动端——干脆别试原生 API,那是另一套逻辑。



















