拖拽失败主因是dragover未调e.preventDefault()或dragstart未设dataTransfer.setData();移动端原生不支持,须降级为file输入。

设了 draggable="true" 但拖不动,或 drop 根本不触发——八成是没在 dragover 里调 e.preventDefault(),或者 dragstart 没调 dataTransfer.setData()。
为什么 dragover 必须每次调 preventDefault()
浏览器只把 dragover 当作“是否允许投放”的实时询问。不阻止默认行为,它就认定“此处不可放”,直接丢弃后续 drop,光标变禁止符号,控制台也不报错。
- 必须在目标容器(比如一个
<div id="drop-zone">)上监听 <code>dragover,不能只绑在document或父级上 - 每次事件触发都得执行
e.preventDefault(),不是绑一次就一劳永逸 - 别在
dragenter里preventDefault()——它只管“进不进”,不管“放不放” - 如果目标区域是动态渲染的(比如 Vue 的
v-for列表),确保绑定时机在 DOM 挂载之后,或用事件委托到稳定父容器 - 至少写一行:
e.dataTransfer.setData('text/plain', '')(空字符串也行) - 传业务数据时推荐自定义 MIME 类型,比如
'text/id'或'application/json',避免和系统类型(如'text/uri-list')冲突 -
e.dataTransfer.effectAllowed = 'move'建议加上,否则某些浏览器可能限制投放效果 - 别在
dragstart里读取异步数据(比如fetch),dataTransfer对象只在拖拽生命周期内有效,drop 后再访问会返回空 - 先转成数组:
Array.from(e.dataTransfer.files),才能用map、filter等方法 -
getData()的 MIME 类型参数必须和setData()时完全一致(大小写敏感),setData('text/plain', 'x')就只能用getData('text/plain') - 校验文件类型别写死
file.type === 'image/jpeg',改用file.type.startsWith('image/')覆盖 png/webp/svg - 限制大小:
if (file.size > 20 * 1024 * 1024),避免大日志或视频卡死页面 - 预览优先用
URL.createObjectURL(file),比FileReader读 base64 更轻量,尤其对大图 - 别试图用
touchstart+touchmove模拟并派发DragEvent——浏览器不认,dataTransfer是只读空对象 - 移动端上传必须降级为
<input type="file">,或用第三方库(如SortableJS的 touch 插件)做视觉拖动,底层仍是点击触发 - 如果项目必须跨端,建议在初始化时用
'ontouchstart' in window或matchMedia('(hover: none)')提前判断,分流逻辑
dragstart 不设 dataTransfer 就等于没拖
draggable="true" 只是开关,不自动传数据。没设 dataTransfer,整个拖拽链就断在起点:Chrome/Firefox/Safari 全部静默失败,drop 压根不会触发。
拖拽上传时 drop 里怎么安全取文件
用户拖进来的文件在 e.dataTransfer.files 里,但它是个只读 FileList,不是数组,且类型校验必须严格匹配。
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
立即学习“前端免费学习笔记(深入)”;
移动端根本没这回事
原生 drag/drop API 在 iOS 和 Android 上全都不支持。你写的 dragstart、dragover、drop 在手机 Safari 或 Chrome 里根本不会触发。
最容易被忽略的是:拖拽不是“加个属性就完事”,它是一条脆弱的事件链——draggable="true" 开关、dragstart 存数据、dragover 每次阻止、drop 取数据,缺一不可;而移动端那块,压根没这条链。


















