原生JS实现拖拽排序

news2025/1/11 8:07:56

拖拽(这两个字看了几遍已经不认识了)

说到拖拽,应用场景不可谓不多。无论是打开电脑还是手机,第一眼望去的界面都是可拖拽的,靠拖拽实现APP或者应用的重新布局,或者拖拽文件进行操作文件。

先看效果图,如何实现一个如图HTML元素的拖拽,并排序

HTML中的拖拽事件(drag & drop)

参考MDN中文文档

事件类型

  • drag : 当拖拽的元素或者选中的文本时触发* dragend : 当拖拽元素结束时触发* dragenter : 当拖拽元素或选中的文本到一个可释放目标时触发* dragleave : 当拖拽元素或选中的文本离开一个可释放目标时触发* dragover : 当元素或选中的文本被拖到一个可释放目标上时触发(每 100 毫秒触发一次)* dragstart : 当用户开始拖拽一个元素或选中的文本时触发* drop : 当元素或选中的文本在可释放目标上被释放时触发Coding

写一段简单的CSS和html ,实现初始的页面

css*{margin: 0;padding: 0;box-sizing: border-box;}ul{margin: 200px auto;width: 200px;list-style-type: none;}li{margin: 5px;text-align: center;width: 200px;height: 30px;background: skyblue;}.list .moving{background: transparent;color: transparent;border: 1px dashed #ccc;} 
html<ul class="list"><li >1</li><li >2</li><li >3</li><li >4</li><li >5</li></ul> 

此时我们的页面如下图

现在还不可以进行拖拽操作,为了可以实现拖拽操作,我们必须给每个元素设置 draggable=“true”

 <ul class="list"><li draggable="true">1</li><li draggable="true">2</li><li draggable="true">3</li><li draggable="true">4</li><li draggable="true">5</li></ul> 

元素已经可以基础的拖拽

接下来我们需要在JS中对DOM元素进行一系列操作来实现对应的效果

1.实现拖出去的元素,原位置样式变为透明虚线
2.实现拖动到其他元素上时,列表顺序发生改变

 let list = document.querySelector('.list')let currentLi// 记录拖拽元素 

我们用事件委托,监听 “dragstart” 事件,给拖动的元素添加类名,修改样式,这里会出现奇怪的一幕就是,拖动的样式和原来的样式同时变成了透明。

 list.addEventListener('dragstart',(e)=>{e.dataTransfer.effectAllowed = 'move' // 拖动样式改为 "move"currentLi = e.targetcurrentLi.classList.add('moving')}) 

这里会出现奇怪的一幕就是,拖动的样式和原来的样式同时变成了透明。这是因为跟随鼠标拖动的元素的样式在拖动的那一刻是原始元素的样式,所以也会添加"moving", 那么在这里我们加一个异步

 list.addEventListener('dragstart',(e)=>{e.dataTransfer.effectAllowed = 'move'currentLi = e.targetsetTimeout(()=>{currentLi.classList.add('moving')})}) 

到这里距离目标又更近了一步,

接下来我们需要在拖动的过程中对列表的元素进行重新的排序

Node.insertBefore():方法在参考节点之前插入一个拥有指定父节点的子节点

 list.addEventListener('dragenter',(e)=>{e.preventDefault()// 阻止默认事件if(e.target === currentLi||e.target === list){ // 当移动到当前拖动元素,或者父元素上面我们不做操作return}let liArray = Array.from(list.childNodes)let currentIndex = liArray.indexOf(currentLi) // 获取到拖动元素的下标let targetindex = liArray.indexOf(e.target) // 获取到目标元素的下标if(currentIndex<targetindex){list.insertBefore(currentLi,e.target.nextElementSibling)}else{list.insertBefore(currentLi,e.target)}}) 

最后我们需要在拖拽结束将元素的moving类名移除,以及阻止拖拽到一个目标上的默认事件(否则会出现禁止)

 list.addEventListener('dragover',(e)=>{e.preventDefault()})list.addEventListener('dragend',(e)=>{currentLi.classList.remove('moving')}) 

至此,一个简单的拖拽排序功能就实现了

完整代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style> *{margin: 0;padding: 0;box-sizing: border-box;}ul{margin: 200px auto;width: 200px;list-style-type: none;}li{margin: 5px;text-align: center;width: 200px;height: 30px;background: skyblue;}.list .moving{background: transparent;color: transparent;border: 1px dashed #ccc;} </style>
</head>
<body><ul class="list"><li draggable="true">1</li><li draggable="true">2</li><li draggable="true">3</li><li draggable="true">4</li><li draggable="true">5</li></ul><script> let list = document.querySelector('.list')let currentLilist.addEventListener('dragstart',(e)=>{e.dataTransfer.effectAllowed = 'move'currentLi = e.targetsetTimeout(()=>{currentLi.classList.add('moving')})})list.addEventListener('dragenter',(e)=>{e.preventDefault()if(e.target === currentLi||e.target === list){return}let liArray = Array.from(list.childNodes)let currentIndex = liArray.indexOf(currentLi)let targetindex = liArray.indexOf(e.target)if(currentIndex<targetindex){ list.insertBefore(currentLi,e.target.nextElementSibling)}else{list.insertBefore(currentLi,e.target)}})list.addEventListener('dragover',(e)=>{e.preventDefault()})list.addEventListener('dragend',(e)=>{currentLi.classList.remove('moving')}) </script>
</body>
</html> 

最后

最近还整理一份JavaScript与ES的笔记,一共25个重要的知识点,对每个知识点都进行了讲解和分析。能帮你快速掌握JavaScript与ES的相关知识,提升工作效率。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/379995.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

动态IP与静态ip的区别是什么

1、DHCP IP即动态ip&#xff0c;可以自动获取IP地址。静态ip上网又被称为固定IP地址上网&#xff0c;需要手动设置IP地址。2、在网速上&#xff0c;动态ip和静态ip没有区别。3、动态ip不是一个真实的IP地址&#xff0c;静态IP是可以直接上网的IP地址。静态ip和动态ip设置方法&a…

datahub部署

硬件要求DataHub官方要求的最低配置为&#xff1a;2 个 CPU、8GB RAM、2GB 交换区和 10GB 磁盘空间。本文的示例环境为阿里云centos8云服务器安装dockeryum -y install docker sudo systemctl start docker安装docker-composecurl -SL https://get.daocloud.io/docker/compose…

Python3-列表

Python3 列表 序列是 Python 中最基本的数据结构。 序列中的每个值都有对应的位置值&#xff0c;称之为索引&#xff0c;第一个索引是 0&#xff0c;第二个索引是 1&#xff0c;依此类推。 Python 有 6 个序列的内置类型&#xff0c;但最常见的是列表和元组。 列表都可以进…

VUE前端常问面试题

文章目录一、VUE前端常问面试题二、文档下载地址一、VUE前端常问面试题 1、MVC和MVVM 区别 MVC&#xff1a;MVC全名是 Model View Controller&#xff0c;即模型-视图-控制器的缩写&#xff0c;一种软件设计典范。 Model(模型)&#xff1a;是用于处理应用程序数据逻辑部分。通…

力扣-第二高的薪水

大家好&#xff0c;我是空空star&#xff0c;本篇带大家了解一道中等的力扣sql练习题。 文章目录前言一、题目&#xff1a;176. 第二高的薪水二、解题1.正确示范①提交SQL运行结果2.正确示范②提交SQL运行结果3.正确示范③提交SQL运行结果4.正确示范④提交SQL运行结果5.其他总结…

[chapter 11][NR Physical Layer][Layer Mapping]

前言&#xff1a;这里参考Curious Being系列 &#xff0c;简单介绍一下NR 5G 物理层核心技术层映射.我们主要讲了一下what is layer Mapping, why need layer Mapping, how layer Mapping 参考文档&#xff1a;3GPP 38.211- 6.3.1.3 Layer mapping《5G NR Physical Layer | Cha…

仓储调度|库存管理系统

技术&#xff1a;Java、JSP等摘要&#xff1a;随着电子商务技术和网络技术的快速发展&#xff0c;现代物流技术也在不断进步。物流技术是指与物流要素活动有关的所有专业技术的总称&#xff0c;包括各种操作方法、管理技能等&#xff0c;物流业采用某些现代信息技术方面的成功经…

智能客服vs人工客服,两者真水火不容?

随着互联网、智能技术的不断发展&#xff0c;Chatgpt的到来引发各界热议&#xff0c;不少人认为Chatgpt将给各个领域带来翻天覆地的变化。而在客服行业&#xff0c;AI产物——智能客服早已落地并且被广泛运用&#xff0c;在Chatgpt爆火的这段时间&#xff0c;有望率先融合应用C…

虚拟局域网VLAN的实现机制

虚拟局域网VLAN的实现机制1.IEEE 802.1Q帧2.交换的端口类型AccessTrunkHybrid&#xff08;华为特有&#xff09;1.IEEE 802.1Q帧 IEEE802.1Q帧&#xff08;也称Dot One Q帧&#xff09;对以太网的MAC帧格式进行了扩展&#xff0c;插入了4字节的VLAN标记。 2.交换的端口类型 A…

实验进行时

torch与cuda版本配对&#xff1a;Previous PyTorch Versions | PyTorch 删除虚拟环境&#xff1a;conda remove -n mygcn --all 时序KG 删掉1.7.1torch装1.8.0&#xff0c;解决报错RuntimeError: CUDA error: no kernel image is available for execution on the 已经成功运…

数组模拟常见数据结构

我们来学习一下用数组模拟常见的数据结构&#xff1a;单链表&#xff0c;双链表&#xff0c;栈&#xff0c;队列。用数组模拟这些常见的数据结构&#xff0c;需要我们对这些数据结构有一定的了解哈。单链表请参考&#xff1a;http://t.csdn.cn/SUv8F 用数组模拟实现比STL要快&a…

PCB板漏孔、漏槽怎么办?看工程师避坑“SOP”

本文为大家介绍PCB画板时常见的钻孔问题&#xff0c;避免后续踩同样的坑。钻孔分为三类&#xff0c;通孔、盲孔、埋孔。不管是哪种孔&#xff0c;孔缺失的问题带来的后果是直接导致整批产品不能使用。因此钻孔设计的正确性尤为重要。 案例讲解 问题1&#xff1a;Altium设计的文…

Linux 进程:进程状态

目录一、进程状态1.简单分类2.详细分类&#xff08;1&#xff09;运行态&#xff08;2&#xff09;休眠态[1]可中断休眠态[2]不可中断休眠态&#xff08;3&#xff09;停止状态&#xff08;4&#xff09;死亡状态&#xff08;5&#xff09;僵死状态二、特殊进程1.僵尸进程2.孤儿…

Java-枚举类的使用(详解)

枚举类的使用前言一、何为枚举类&#xff1f;二、自定义枚举类&#xff08;JDK1.5之前&#xff09;1、实现1.1 属性1.2 构造器2、代码演示三、用关键字enum定义枚举类&#xff08;JDK 1.5&#xff09;1、实现1.1 属性1.2 构造器2、代码演示四、Enum类的方法五、实现接口的枚举类…

GeoServer 存在 sql 注入漏洞

漏洞描述 GeoServer 是一个允许用户共享和编辑地理空间数据的开源软件服务器&#xff0c;支持 OGC Filter expression 和 OGC Common Query Language 语言&#xff0c;使用 PostGIS Datastore 作为数据库。PostGIS是PostgreSQL数据库的扩展程序&#xff0c;增加了数据库对地理…

HTMLCollection 和 NodeList 区别

Node 和 Element DOM 是一棵树&#xff0c;所有节点都是 NodeNode 是 Element 的基类Element 是其他 HTML 元素的基类&#xff0c;如 HTMLDivElement HTMLCollection 和 NodeList HTMLCollection 是 Element 的集合NodeList 是 Node 的集合 <body><p id"p1&qu…

什么是IP地址?

IP协议中还有一个非常重要的内容&#xff0c;那就是给因特网上的每台计算机和其它设备都规定了一种地址&#xff0c;叫做“IP 地址”。由于有这种地址&#xff0c;才保证了用户在连网的计算机上操作时&#xff0c;能够高效而且方便地从千千万万台计算机中选出自己所需的对象来。…

堆叠和集群(详细的理论和实验)

随着企业的发展&#xff0c;企业网络的规模越来越大&#xff0c;这对企业网络提出了更高的要求&#xff1a;更高的可靠性、更低的故障恢复时间、设备更加易于管理等。传统的园区网高可靠性技术出现故障时切换时间很难做到毫秒级别、实现可靠性的方案通常为一主一备&#xff0c;…

前端一面react面试题指南

React 事件机制 <div onClick{this.handleClick.bind(this)}>点我</div>React并不是将click事件绑定到了div的真实DOM上&#xff0c;而是在document处监听了所有的事件&#xff0c;当事件发生并且冒泡到document处的时候&#xff0c;React将事件内容封装并交由真正…

2023年3月实时获取地图边界数据方法,省市区县街道多级联动【附实时geoJson数据下载】

首先&#xff0c;来看下效果图 在线体验地址&#xff1a;https://geojson.hxkj.vip&#xff0c;并提供实时geoJson数据文件下载 可下载的数据包含省级geojson行政边界数据、市级geojson行政边界数据、区/县级geojson行政边界数据、省市区县街道行政编码四级联动数据&#xff0…