必须在dragover和drop事件中均调用event.preventDefault(),否则浏览器将拖拽视为导航行为导致dataTransfer.files为空;优先使用files获取文件,items仅适用于文件夹检测但兼容性差。

HTML 本身不接收拖拽文件,必须靠 JavaScript 监听事件并阻止默认行为,否则浏览器会直接打开或下载文件。
为什么 drop 事件里拿不到文件?
根本原因是没阻止 dragover 的默认行为 —— 浏览器默认把拖入当作“打开文件”处理,drop 根本不会触发。
- 必须在
dragover回调中立刻调用e.preventDefault() - 仅在
drop里调用preventDefault()不够,dragover被拦住才是关键 - 部分旧版 Chrome 还要求设置
e.dataTransfer.dropEffect = 'copy'(虽非必需,但加了更稳)
dataTransfer.files 和 dataTransfer.items 怎么选?
files 是最常用、最可靠的入口,适用于所有单文件/多文件拖拽场景;items 主要用于判断是否拖入了文件夹,但兼容性差(Safari 不支持 webkitGetAsEntry)。
-
e.dataTransfer.files返回FileList,每个项是标准File对象,含name、size、type、lastModified -
e.dataTransfer.items是DataTransferItemList,需遍历并用item.webkitGetAsEntry()判断是否为目录,但该方法已废弃且无跨浏览器替代方案 - 若只需上传文件(不含子目录),只读
files就够了,别绕弯走items
怎么安全地从 drop 提取文件并校验?
拿到 files 后不能直接传给后端,得先过滤非法输入,避免无效请求或前端崩溃。
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
- 检查
files.length === 0:空拖拽(比如只拖了文本)会进drop但files为空 - 用
file.type或file.name.split('.').pop().toLowerCase()做类型白名单,别只信type(可被伪造) - 用
file.size > 10 * 1024 * 1024拦截超大文件,防止 FileReader 卡死或内存溢出 - 对图片预览,优先用
URL.createObjectURL(file),比FileReader.readAsDataURL()更快更省内存
移动端和降级方案怎么处理?
桌面端拖拽在 iOS / Android 上基本不可用 —— Safari 和 Chrome for Android 均不触发 dragover/drop,这不是 bug,是规范限制。
- 必须保留
作为兜底,样式可覆盖隐藏,用按钮触发click() - 不要依赖
draggable="true"来“启用”拖拽,它只影响元素能否被拖出,跟接收无关 - 检测
'onDrop' in document.createElement('div')没意义,应直接按平台特征判断:移动端 UA + 不支持dataTransfer.files就切回 input
真正容易被忽略的是:拖拽区域的边界判定。很多代码只监听容器自身的 dragover,但用户手指稍微划出容器就触发 dragleave,导致高亮闪退。稳妥做法是用 dragenter 加计数器,配合 dragleave 减计数,仅当计数归零才还原样式 —— 这点连不少开源库都漏掉。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










