1.首先,为了使元素可拖动,要先设置元素为可拖拽
- 方法:添加draggable属性,设置为 true
- 注意:链接和图像默认就支持拖拽,另外,如果一个元素中的文本被选中,那么这个元素和他的文本节点此时都支持被拖拽。
<body style="padding:30px;">
<div class="item">
<h3 draggable="true">我是被允许拖拽的h3元素</h3>
</div>
<div class="item">
<a href="http://www.baidu.com/">a链接</a>
</div>
<div class="item">
<img src="timg.jpg" alt="" width="200">
</div>
<div class="item">
<h3>选中文字后可被拖拽</h3>
</div>
</body>
<script>
document.ondragstart = function(){
console.log('dragstart')
}
</script>

2.拖拽事件监听
- 拖拽事件一律使用(推荐)document监听,拖拽事件分2种,一种针对的是被拖拽的元素,第二种针对被拖拽的元素经过的容器
事件名称 |
事件对象(e.target) |
说明 |
ondrag |
被拖拽的元素 |
元素被拖拽期间(持续)触发 |
ondragstart |
被拖拽的元素 |
开始拖拽元素时触发(推荐使用它记录被拖拽的元素) |
ondragend |
被拖拽的元素 |
元素拖拽结束时触发 |
ondragenter |
接收容器 |
被拖拽的元素进入当前容器范围内时触发此事件 |
ondragover |
接收容器 |
被拖拽的元素停留在当前容器范围内(持续)触发此事件 |
ondragleave |
接收容器 |
被拖拽的元素离开当前容器范围内时触发此事件 |
ondrop |
接收容器 |
释放鼠标键时触发此事件(触发时间早于ondragend) |
- 注意:浏览器默认阻止ondrop事件,需要在ondragover事件中阻止默认事件它才能被触发
3.完整的拖拽实例
- 哪个元素被拖拽:可以在ondragstart事件中获取被拖拽的元素,并保存,问题1解决
- 哪个容器负责接收:实际操作中,拖拽结束时经过的容器就是接收的容器,而能在此时获得接收容器的事件只能是drop事件(而drop事件默认被屏蔽,所以需要在ondragover事件中释放此事件)
<script>
var dragNode = null
document.ondragstart = function (e) {
dragNode = e.target
dragNode.style.opacity = 0.5
}
document.ondragend = function (e) {
e.target.style.opacity = 1
dragNode = null
}
document.ondragover = function (e) {
e.preventDefault()
}
document.ondrop = function (e) {
var targetBox = e.target
if(targetBox.matches(".box")){
targetBox.appendChild(dragNode)
}
}
</script>
4.优化
- 存在的问题:前面的案例中我们使用了一个全局变量来存储被拖拽的元素,但是使用全局变量容器污染全局
- 解决办法:在拖拽事件中,事件对象event有一个dataTransfer属性对象,用来保存和读取拖放相关的数据
方法 |
说明 |
e.dataTransfer.setData(key,data) |
设置数据(只能传入数字或者字符串) |
e.dataTransfer.getData(key) |
取数据(数字或者字符串) |
e.dataTransfer.clearData(key) |
清空数据 |
- 代码实现:使用e.dataTransfer记录被拖拽元素的id属性值,从而通过这个值获取获取到被拖拽的元素
<script>
document.ondragstart = function (e) {
if(!e.target.id && e.target.nodeType === 1){
e.target.id = "dragTest"
}
e.dataTransfer.setData("id",e.target.id)
e.target.style.opacity = 0.5
}
document.ondragend = function (e) {
e.target.style.opacity = 1
}
document.ondragover = function (e) {
e.preventDefault()
}
document.ondrop = function (e) {
var targetBox = e.target
var id = e.dataTransfer.getData("id")
var dragNode = document.querySelector("#"+id)
if(targetBox.matches(".box")){
targetBox.appendChild(dragNode)
}
}
</script>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了