原生拖拽上传需显式调用 preventdefault() 处理 dragover/dragenter 事件,确保目标元素有宽高;filelist 需转数组并过滤非 file 项及校验大小。

拖拽上传不是非得用第三方库,原生 HTML5 的 DragEvent 和 File API 就能搭出可用原型——但直接写容易卡在事件不触发、文件读取失败或 UI 响应错乱上。
为什么 dragover 事件没生效?
这是最常卡住的第一步:拖文件进页面,光标一直是“禁止”图标,drop 根本不触发。根本原因是浏览器默认会阻止 dragover 的默认行为,必须显式调用 preventDefault()。
-
dragover和dragenter都要加e.preventDefault(),只加一个不够 - 别只监听
body或大容器,确保目标元素有明确宽高(空div默认高为 0,拖不进去) - 避免在
dragover里做耗时操作(比如实时预览),否则拖拽会卡顿
如何安全读取拖入的 FileList?
event.dataTransfer.files 是只读的 FileList,不是数组,不能直接用 map 或 forEach。而且它可能包含目录(Chrome 支持拖文件夹)、重复项或非法类型。
- 先转成数组:
Array.from(e.dataTransfer.files) - 过滤掉非文件项:
file instanceof File(注意:File是Blob子类,但Directory不是) - 检查大小:
file.size (例如限制 10MB),超限跳过或报错 - 不要直接用
FileReader.readAsDataURL()读大文件,内存暴涨;优先用readAsArrayBuffer或分片上传逻辑
拖拽状态怎么同步到 UI?
用户需要视觉反馈:拖入时高亮区域、悬停时显示提示、释放后禁用交互。靠 CSS class 切换最轻量,但要注意事件冒泡和多次触发。
- 在
dragenter加 class,在dragleave移除 —— 但子元素进出也会触发,要用e.relatedTarget判断是否真正离开目标区域 - 更稳的做法:只在
dragenter设标记,在dragover持续更新 UI,drop或dragend清除 - 禁用按钮或遮罩层要在
drop后立刻生效,别等上传完成才锁,防止重复提交
真正麻烦的不是拖拽本身,而是边界情况:用户中途取消、文件名含特殊字符、移动端 Safari 对 dataTransfer 支持残缺、连续快速拖入导致事件队列堆积。原型阶段先守住 dragover+drop 主链路,其他容错往后放。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











