需监听dragenter、dragover、dragleave和drop事件:dragenter添加高亮,dragover必须preventdefault()启用drop,dragleave用relatedtarget过滤防误触发,drop中读取datatransfer.files。

如何监听拖拽进入和离开上传区域
拖拽上传的核心不是靠点击触发,而是捕获浏览器原生的 dragenter、dragover、dragleave 和 drop 事件。其中 dragover 必须调用 event.preventDefault(),否则浏览器会执行默认行为(比如打开文件),导致 drop 事件根本不会触发。
常见错误是只监听 drop 却忽略 dragover 的阻止,默认行为没拦住,整个拖拽流程就静默失败了。
-
dragenter:用户首次把文件拖进区域时触发,适合添加高亮样式 -
dragover:只要文件还在区域内持续触发,必须preventDefault()才能启用drop -
dragleave:鼠标移出区域时触发(注意:子元素进出也会触发,需用relatedTarget过滤) -
drop:松手后触发,从event.dataTransfer.files取文件列表
如何安全读取拖入的文件并预览
拿到 FileList 后不能直接当路径用——浏览器出于安全限制,不允许 JS 获取真实文件路径。需要通过 FileReader 读取内容或生成预览 URL。
对图片类文件,优先用 URL.createObjectURL(file),比 FileReader.readAsDataURL() 更轻量、无编码开销;非图片文件(如 PDF、TXT)则需根据后缀判断是否支持内联预览,否则只能显示文件名和大小。
- 避免在循环中反复调用
FileReader,容易因闭包导致读错文件内容 - 使用
URL.createObjectURL()后,记得在不再需要时调用URL.revokeObjectURL()防止内存泄漏 - 检查
file.type和file.name后缀,不要仅依赖后者做类型判断(用户可伪造)
如何处理多文件、大文件及取消上传逻辑
拖拽支持一次选中多个文件,event.dataTransfer.files 是只读的 FileList,不是数组,需用 Array.from() 转换才能用 map、filter 等方法。
大文件(如 >100MB)不建议前端全量读取,应直接分片上传或走 fetch 流式提交。如果只是校验大小,直接读 file.size 即可,无需触发读取。
- 限制单次上传数量:用
files.length > 5提前提示,避免 UI 卡顿 - 限制单个文件大小:比如
if (file.size > 50 * 1024 * 1024)拦截超限文件 - 取消上传本质是 abort
fetch或XMLHttpRequest,需保存 controller 实例,不能靠删 DOM 解绑
为什么 drop 区域点击没反应?input[type=file] 怎么隐藏又保留功能
纯 div 拖拽区无法触发文件选择框,必须背后关联一个不可见但可交互的 <input type="file">。隐藏它不能只用 display: none 或 visibility: hidden,那样会禁用其交互能力。
真正可行的方式是用 CSS 把 input 缩成 1px、透明、绝对定位压在拖拽区下方,并设置 z-index 确保能被点击穿透(或用 pointer-events: none 让上层容器接收事件,再手动触发 input.click())。
- 别用
opacity: 0+pointer-events: none组合,会导致 click 失效 - 移动端 Safari 对
label[for]关联input支持不稳定,推荐直接input.click() - 触发
click()前确保input已挂载到 DOM,否则部分浏览器会静默忽略
拖拽上传看似简单,实际卡点都在事件拦截时机、文件对象生命周期管理和 input 隐藏方式这三个地方。漏掉任何一个,都会表现为“拖进去没反应”或“点了没弹窗”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











