dragstart不触发需先检查三件事:属性值是否为字符串"true"、元素是否有尺寸(如min-height)、是否存在user-select:none或pointer-events:none等样式拦截。

dragstart事件不触发,先看这三件事
浏览器看到 draggable="true" 只会改光标样式,不会自动绑事件。光标变手形 ≠ dragstart 被调用。
- 检查属性值是否为字符串
"true":写成draggable(无值)、draggable={true}(React JSX)或draggable="1"都无效 - 确保元素有尺寸:空
<div> 没宽高时,浏览器判定“不可交互”,<code>dragstart不触发;加min-height: 24px或padding: 4px即可 - 排查样式拦截:
user-select: none或pointer-events: none的父级会直接阻止mousedown,dragstart更不可能触发 - 目标容器必须监听
dragover,且回调中必须写e.preventDefault();e.stopPropagation()或return false都不行 - 只监听
drop或只在dragenter里preventDefault(),drop仍不会来 - 容器若为空(比如空
<ul></ul>),需设min-height: 1px或伪元素撑开,否则dragover根本不派发 - 必须降级:用
touchstart/touchmove/touchend+CSS transform手动实现拖动视觉,或引入SortableJS、interact.js这类已做平台适配的库 - 若坚持原生 API,至少检测
'ontouchstart' in window,并切换为“长按激活 + 点击插入”模式
drop事件完全不执行?90%卡在dragover
drop 是否触发,由 dragover 阶段决定——不是可选项,是硬性闸门。
移动端拖拽失效不是bug,是平台限制
iOS Safari 和多数 Android WebView 对原生 drag/drop 支持极弱:从 iOS 15.4 开始仅对 <img> 有基础支持,<div draggable="true"> 基本静默失败。<ul>
<li>别试图用 <code>ontouchstart 模拟 dragstart —— touch 事件和 drag 事件互斥,强行混用会导致冲突或卡顿
dataTransfer拿不到数据?类型和调用时机都得对
e.dataTransfer.getData('text/plain') 返回空字符串,几乎全是 setData() 没写对。
-
setData()必须在dragstart回调里调用,且类型推荐"text/plain";"Text"(IE 风格)或自定义类型如"mydata"在 Firefox 中会静默失败 - 值只能是字符串:
e.target.id可以,JSON.stringify(obj)可以,但obj或e.targetDOM 节点直接传会失败 - 动态渲染的列表(Vue/React)容易漏绑事件:用事件委托,给父容器监听
dragstart,再用e.target.matches("[draggable='true']")过滤目标,避免新增节点没监听器
真正麻烦的是跨设备状态同步——DOM 插入位置和框架 state 不一致时,下一次 drop 拿到的 e.target 还是旧节点。ID 映射比 DOM 顺序更可靠,这点容易被忽略。











