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

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


















