draggable="true"仅开启拖拽开关,需显式绑定dragstart事件、设置dataTransfer数据、防止默认行为且目标需监听dragover并preventDefault;移动端不支持原生drag/drop,须降级处理。

draggable="true" 只是打开拖拽开关,不配事件、不传数据、不阻止默认行为,拖拽一定失败。
dragstart 事件没触发?先看这三件事
元素光标变手形 ≠ dragstart 被触发。浏览器不会自动绑定事件,必须显式注册。
-
draggable="true"必须写在被拖元素上(),或即使加了也无效- 必须用
addEventListener('dragstart', ...)或内联ondragstart绑定回调;只设属性不写事件监听,dragstart根本不会来event.dataTransfer.setData('text/plain', 'some-id')必须在dragstart回调里执行,且 type 建议用'text/plain'或'text/html'—— 自定义类型如'mydata'在 Firefox 中会静默失败- 空
没宽高时,浏览器判定“不可交互”,dragstart不触发;加min-height: 24px或padding: 4px就能解决- 检查是否被样式拦住:
user-select: none或pointer-events: none会让mousedown都失效,dragstart更不可能触发drop 事件不执行?关键在 dragover
drop不执行,90% 是因为dragover没拦住浏览器默认拦截逻辑。它不是可选步骤,而是硬性前提。- 目标容器必须监听
dragover,且回调中必须调用e.preventDefault()——e.stopPropagation()、return false都不行 - 只监听
drop是无效的;浏览器在dragover阶段就决定是否允许投放,没preventDefault(),drop根本不会派发 - 目标容器若为空 ,确认它没被
display: none或visibility: hidden隐藏,否则无法命中- Safari 对
effectAllowed和dropEffect匹配更敏感:建议在dragstart里设e.dataTransfer.effectAllowed = 'move',在dragover里设e.dataTransfer.dropEffect = 'move'移动端完全不支持原生 drag/drop
iOS Safari 和 Android Chrome 均不触发
dragstart/drop等事件。draggable="true"在移动端基本失效,这不是兼容性问题,是平台级限制。- 别直接照搬桌面代码;需降级为
touchstart/touchmove/touchend+CSS transform手动模拟 - 或引入轻量库如
interact.js或sortablejs,它们内部已做平台兼容处理 - 若坚持用原生 API,至少检测
'ontouchstart' in window并切换为点击+长按激活模式
drop 里拿不到正确目标?别依赖 event.target
drop事件中的event.target可能是子元素(比如你拖到一个带文字的,target反而是里面),不是你绑定事件的容器本身。- 用
event.currentTarget获取你实际监听的父容器 - 或者把
drop和dragover显式绑定到最外层容器(如class="column"),避免事件冒泡干扰 -
event.dataTransfer.getData('text/plain')获取数据时,type 必须和setData()时一致,否则返回空字符串
真正麻烦的不是写几行事件监听,而是跨浏览器拖拽状态同步、释放位置计算精度、与滚动容器协同、以及键盘用户如何“拖拽”——这些细节往往第一次上线后才暴露出来。
- Safari 对
- 必须用
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











