如何用javascript实现拖放功能【教程】
技术百科
夜晨
发布时间:2026-01-28
浏览: 次 原生拖放API中drop不触发的根本原因是浏览器默认阻止dragover事件,必须在dragover中调用event.preventDefault();dataTransfer仅支持字符串,推荐用ID查表还原数据;非draggable元素需手动设置draggable="true";移动端需touch事件模拟。
原生 JavaScript 的拖放(Drag and Drop)API 表面简单,实际容易卡在 dragover 事件被忽略、drop 不触发、或数据传不进目标元素上——根本原因不是写法错,而是浏览器默认阻止了这些事件的默认行为。
为什么 drop 事件完全不触发?
因为浏览器对 dragenter 和 dragover 默认不做任何事,更不会让 drop 发生。你必须显式调用 event.preventDefault(),而且得在 dragover(以及可选的 dragenter)里调用。
-
dragover是唯一必须阻止默认行为的事件;漏掉它,drop永远不会触发 -
dragenter阻止与否不影响drop,但能控制“进入目标区域”的视觉反馈(比如加 class) - 不能只在
drop里preventDefault()——太晚了,浏览器已经跳转或下载了
dataTransfer 只能传字符串?怎么传 DOM 元素或对象?
dataTransfer 的 setData() 方法只接受字符串类型值,但你可以用它传递标识符(如 ID 或索引),再在 drop 时查表还原真实数据。
- 不要尝试
setData('text/plain', JSON.stringify(obj))后在drop里JSON.parse()——跨域或安全策略可能拦截 - 推荐做法:拖拽开始前把源元素的引用缓存在全局 Map 或数组中,
setData('text/id', 'item-123'),drop时用该 ID 查找对应数据 - 如果只是移动 DOM 节点,直接
event.target.appendChild(draggedElement)更可靠,无需走dataTransfer
如何让非 draggable="true" 元素可拖?
只有设置了 draggable="true" 的元素(或表单控件、图片等原生可拖元素)才能触发拖拽起点。但你可以用 JS 主动触发:
立即学习“Java免费学习笔记(深入)”;
- 监听
mousedown,然后调用element.setPointerCapture()+element.draggable = true动态开启(注意后续要恢复) - 更稳妥的做法:在目标元素上加
draggable="true",再用 CSSuser-select: none
避免文字被误选
- 移动端不支持原生 drag API,必须用
touchstart/touchmove模拟——这点常被忽略,导致 H5 页面拖放失效
最易被绕过的细节是:拖放过程中若鼠标移出窗口(比如切到别的标签页),dragend 仍会触发,但 drop 已经没了;此时应靠 dragleave 或定时器兜底清理状态。
# ai
# 浏览器
# app
# css
# js
# json
# go
# javascript
# java
# class
# 字符串
# 为什么
# Event
# map
# select
# 标识符
# 跨域
# 字符串类型
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- Python函数接口稳定性_版本演进解析【指导】
- Win10 BitLocker加密教程 Win10
- Linux如何安装Tomcat应用服务器_Linu
- php下载安装选zip还是msi格式_两种安装包对
- 如何使用Golang进行HTTP服务性能测试_测量
- Win11相机打不开提示错误怎么修_相机权限开启与
- win11如何清理传递优化文件 Win11为C盘瘦
- 如何在 Go 中可靠地测试含 time.Time
- Win11怎么查看wifi信号强度_检测Windo
- Win10系统怎么查看显卡温度_Win10任务管理
- Python深度学习实战教程_神经网络模型构建与训
- Windows系统被恶意软件破坏后的恢复策略_错误
- Win11截图快捷键是什么_Win11自带截图工具
- php订单日志怎么导出excel_php导出订单日
- Python正则表达式实战_模式匹配说明【教程】
- Go 语言标准库为何不提供泛型 Contains
- 如何在Golang中实现微服务负载均衡_Golan
- Win11怎么关闭内容自适应亮度_Windows1
- php订单日志怎么按状态筛选_php筛选不同状态订
- Python包结构设计_大型项目组织解析【指导】
- Go 中 := 短变量声明的类型推导机制详解
- Win11如何设置系统语言_Win11系统语言切换
- C++中的constexpr和const有什么区别
- Win11怎么关闭系统推荐内容_Windows11
- Win11怎么设置DNS服务器_Windows11
- Win11怎么查看显卡温度 Win11任务管理器查
- 如何正确访问 Laravel 模型或对象的属性而非
- Win11怎么关闭右下角弹窗_Win11拦截系统通
- Win11如何设置系统声音_Win11系统声音调整
- Win10怎么更改用户名 Win10修改账户名称操
- Mac如何彻底清理浏览器缓存?(Safari与Ch
- Win11怎么连接蓝牙耳机_Win11蓝牙设备配对
- c++怎么设置线程优先级与cpu亲和性_c++ 多
- 如何在 Go 项目开发中正确处理本地包导入与远程模
- Windows10任务栏图标变成白色文件_Win1
- MAC怎么使用表情符号面板_MAC Emoji快捷
- Windows10电脑怎么设置虚拟内存_Win10
- 电脑无法识别U盘怎么办 Windows磁盘管理与驱
- 静态属性修改会影响所有实例吗_php作用域操作符下
- Win11怎么开启游戏模式_Win11优化游戏帧数
- c# Task.Yield 的作用是什么 它和Ta
- Mac的访达(Finder)怎么用_Mac文件管理
- C++友元类使用场景_C++类间协作设计方式讲解
- Win11怎么开启游戏模式_Windows11优化
- Win11怎么设置虚拟内存_Windows 11优
- Win11怎么设置指纹解锁 Win11笔记本录入指
- c++输入输出流 c++ cin与cout格式化输
- 如何使用Golang实现容器自动化运维_Golan
- MAC如何设置网卡MAC地址克隆_MAC终端修改物
- Win11开机Logo怎么换_Win11自定义启动


QQ客服