跨页面拖拽仅支持文件,需在dragover中preventDefault()阻止默认行为;drop时须同时调用preventDefault()和stopPropagation();files是稳定入口,items在Safari中不可靠;移动端完全不支持,必须降级为input[type=file]。

dragover 事件必须在目标页面监听并调用 preventDefault(),否则跨页面拖拽会失败——浏览器默认行为是打开文件或导航跳转,不是传递数据。
跨页面拖拽只支持文件,不支持自定义文本或 DOM 元素
HTML5 的跨页面拖拽(比如从桌面、资源管理器、另一个浏览器标签页拖入当前网页)仅允许传输真实文件对象,dataTransfer.items 和 dataTransfer.files 是唯二可用入口。你不能像同页面拖拽那样用 setData('text/plain', 'xxx') 传字符串,也不能传 DOM 节点或序列化 JSON。
-
dataTransfer.files是最稳定的选择,返回标准FileList,所有现代浏览器一致支持 -
dataTransfer.items在 Safari 中对非文件项支持差,getAsFile()可能返回null,不建议依赖 - 拖入网页的图片、PDF、TXT 等本地文件都能进
files;但拖入网页链接、书签、纯文本片段则不会出现在files里(它们走的是types+getData,且仅限同源页面间)
drop 事件里必须同时阻止默认行为和事件冒泡
用户把文件从外部拖进页面时,drop 事件默认会触发浏览器打开该文件(如 PDF 用内置查看器、图片新窗口打开),这会中断你的上传逻辑。除了 event.preventDefault(),还应加 event.stopPropagation(),尤其当容器嵌套较深或用了事件委托时:
将 Markdown 文章转换为微信公众号兼容的纯 HTML 格式。当用户要求"转成微信格式"、"生成公众号文章 HTML"、"排版到微信草稿箱"、"微信粘贴格式"时触发。输出带内联样式的纯 HTML,微信编辑器可直接渲染,无需额外适配。支持标题、段落、列表、粗体、行内代码、表格、引用块、代码块、配图的完整转换。
dropZone.addEventListener('drop', (e) => {
e.preventDefault();
e.stopPropagation();
const files = e.dataTransfer.files;
if (files.length === 0) return;
handleFiles(files);
});
- 漏掉
stopPropagation()可能导致父级drop处理器重复执行,或意外触发全局监听器 - 如果 drop 区域是
<div> 且无明确宽高/背景色,拖拽阴影可能“悬空”,实际 drop 不生效——务必设 <code>min-height: 200px或类似兜底样式 - 某些 Electron 或旧版 Chrome 环境下,还需在 HTML 中显式加
dropzone="copy"属性增强兼容性 - 不要尝试监听
touchstart模拟拖拽,无法获取dataTransfer.files - 不要指望 PWA 或 WebView 绕过此限制——WebKit 和 Blink 均未开放该能力
- 必须提供降级方案:
<input type="file">是唯一可靠路径,可配合accept和multiple属性保持体验接近
移动端不支持,别试图 hack
iOS 和 Android 浏览器(包括 Safari、Chrome for iOS)**完全不支持**从文件管理器拖拽文件到网页。这不是配置问题,是平台限制。所谓“跨页面”在这里天然不存在。
真正容易被忽略的一点:跨页面拖拽时,dragenter 和 dragover 在页面首次获得焦点前可能已被触发,但此时 JS 还没加载完。如果你把事件绑定写在 <script></script> 标签底部或异步模块里,很可能错过第一次拖入。稳妥做法是把核心监听逻辑放在 内联脚本中,或至少确保在 DOMContentLoaded 之前完成绑定。










