当前位置: 首页 > article >正文

HTML5 drag API实现列表拖拽排序

拖拽API(Drag and Drop API)是HTML5提供的一组功能,使得在网页上实现拖放操作变得更加简单和强大。这个API允许开发者为网页元素添加拖拽功能,用户可以通过鼠标将元素拖动并放置到指定的目标区域。

事件类型

  • dragstart:事件主体是被拖放元素,在开始拖放被拖放元素时触发。
  • darg:事件主体是被拖放元素,在正在拖放被拖放元素时触发。
  • dragenter:事件主体是目标元素,在被拖放元素进入某元素时触发。
  • dragover:事件主体是目标元素,在被拖放在某元素内移动时触发。
  • dragleave:事件主体是目标元素,在被拖放元素移出目标元素是触发。
  • drop:事件主体是目标元素,在目标元素完全接受被拖放元素时触发。
  • dragend:事件主体是被拖放元素,在整个拖放操作结束时触发。

Draggable属性

HTML元素可以通过设置draggable属性为true来启用拖动。例如:

<div draggable="true">可拖动的元素</div>

DataTransfer对象

这些事件中的event对象包含一个dataTransfer属性,用于存储和传递拖拽的数据。例如,可以使用dataTransfer.setDatadataTransfer.getData方法来设置和获取拖拽的数据。
在这里插入图片描述

列表拖拽排序

演示

列表拖拽排序

完整代码

index.css

.list {padding: 24px 5%;
}.list .list-item {cursor: move;user-select: none;background-color: royalblue;padding: 16px 24px;border-radius: 5px;margin-bottom: 8px;color: white;
}.list-item.moving {background-color: #ccc;color: transparent;
}

index.html

<!doctype html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Document</title><link rel="stylesheet" href="./index.css">
</head>
<body><div class="list"><div draggable="true" class="list-item">1</div><div draggable="true" class="list-item">2</div><div draggable="true" class="list-item">3</div><div draggable="true" class="list-item">4</div><div draggable="true" class="list-item">5</div></div><script src="./index.js"></script>
</body>
</html>

index.js

const list = document.querySelector('.list');
let source;
const handleDragStart = (e) => {setTimeout(() => {e.target.classList.add('moving'); // 设置拖拽样式}, 0);source = e.target;e.dataTransfer.effectAllowed = 'move'; // 设置鼠标样式
}
const handleDragEnter = (e) => {e.preventDefault();if (!source) return;const target = e.target;if (target === list || target === source) return; // 如果进入的元素是父元素或者是被拖动元素则不处理const sourceIndex = Array.from(list.children).indexOf(source); // children是类数组,对象类型const targetIndex = Array.from(list.children).indexOf(target);if (sourceIndex < targetIndex) {// 向下拖list.insertBefore(target, source); // 将目标元素插入到被拖拽元素之前} else {// 向上拖list.insertBefore(source, target); // 将被拖拽元素插入到目标元素之前}
}
const handleDragEnd = (e) => {e.target.classList.remove('moving'); // 移除拖拽样式source = null;
}list.addEventListener('dragstart', handleDragStart);
list.addEventListener('dragenter', handleDragEnter);
list.addEventListener('dragend', handleDragEnd);
list.addEventListener('dragover', e => e.preventDefault()); // 目标元素默认不允许被其他元素进入,被拖拽元素会回到原来位置,需要阻止此默认行为

移动端对 Drag API(Drag and Drop API)的支持

支持较差,原因如下:

  1. 原生支持有限

    • 移动端的触摸事件(touchstarttouchmovetouchend)与鼠标事件不同,很多浏览器不会触发 dragstartdragoverdrop 等拖拽相关的事件。
    • iOS 的 Safari 以及 Android 浏览器大多数情况下 不支持 Drag API,特别是在 WebView 内。
  2. 触摸事件冲突

    • 触摸屏幕时,系统会优先触发 touch 事件,而非 drag 事件,导致 Drag API 无法正常工作。
    • 例如,在 iOS 上,touchmove 会默认滚动页面,而不会触发 drag 相关的事件。
  3. 性能和交互体验

    • 在移动端,拖拽操作通常由 手势 代替,比如滑动、长按拖动等。
    • 例如,HTML5 Draggable 属性 在桌面端可以生效,但在移动端一般不会响应 dragstart 事件。

解决方案:

如果想在移动端实现拖拽效果,推荐使用:

  1. Touch Events 代替 Drag API

    • 监听 touchstarttouchmovetouchend 事件,手动计算元素位置并移动。
  2. 第三方库(更方便)

    • SortableJS(支持 PC 和移动端)
    • Interact.js(提供更丰富的拖拽交互)

示例代码:

如果你想在移动端实现拖拽,建议使用 touchmove 事件,例如:

移动端拖拽

const item = document.getElementById("draggable");let offsetX = 0; // 记录触摸点相对元素左上角的偏移
let offsetY = 0;item.addEventListener("touchstart", function (event) {let touch = event.touches[0];// 获取元素当前位置let rect = item.getBoundingClientRect();// 计算触摸点相对元素左上角的偏移offsetX = touch.clientX - rect.left;offsetY = touch.clientY - rect.top;// 使元素绝对定位item.style.position = "absolute";
});item.addEventListener("touchmove", function (event) {event.preventDefault(); // 阻止滚动let touch = event.touches[0];// 计算元素的新位置,保持触摸点在元素内的相对位置let newLeft = touch.clientX - offsetX;let newTop = touch.clientY - offsetY;item.style.left = newLeft + "px";item.style.top = newTop + "px";
});

这样可以在移动端实现类似拖拽的效果,而不依赖 Drag API

相关文章:

HTML5 drag API实现列表拖拽排序

拖拽API&#xff08;Drag and Drop API&#xff09;是HTML5提供的一组功能&#xff0c;使得在网页上实现拖放操作变得更加简单和强大。这个API允许开发者为网页元素添加拖拽功能&#xff0c;用户可以通过鼠标将元素拖动并放置到指定的目标区域。 事件类型 dragstart&#xff1…...

改变一生的思维模型【11】升维

升维思维模型&#xff1a;突破认知局限的破局法则 一、定义与核心逻辑 升维思维是通过增加分析维度&#xff0c;将问题投射到更高认知层次寻找解决方案的思考方式。其本质是跳出原有竞争维度&#xff0c;在更广阔的空间重构游戏规则。核心逻辑在于&#xff1a;当低维战场陷入…...

【动手学深度学习】#2线性神经网络

主要参考学习资料&#xff1a; 《动手学深度学习》阿斯顿张 等 著 【动手学深度学习 PyTorch版】哔哩哔哩跟李牧学AI 目录 2.1 线性回归2.1.1 线性回归的基本元素线性模型损失函数解析解随机梯度下降 2.1.3 最大似然估计 2.2 线性回归从零开始实现2.2.1 生成数据集2.2.2 读取数…...

计算机网络——NAT

一、什么是NAT&#xff1f; NAT&#xff08;Network Address Translation&#xff0c;网络地址转换&#xff09; 是一种将 私有IP地址 与 公有IP地址 相互映射的技术&#xff0c;主要用于解决IPv4地址不足的问题。它像一名“翻译官”&#xff0c;在数据包经过路由器或防火墙时…...

Stable Deffusion--常见模型插件详解

1.Checkpoint大模型 Checkpoint 是生成图像的基础模型&#xff0c;决定了整体画风如动漫、写实、机甲等。它是必选项&#xff0c;所有图像生成必须基于一个主模型。文件体积较大通常 1.5GB 以上&#xff0c;格式为 .ckpt 或 .safetensors。 存放位置为&#xff1a;\models\Sta…...

防重复提交详解:从前端Vue到后端Java的全面解决方案

防重复提交详解&#xff1a;从前端Vue到后端Java的全面解决方案 一、重复提交问题概述 在Web应用开发中&#xff0c;表单重复提交是一个常见问题&#xff0c;可能导致&#xff1a; 数据库中出现重复记录重复执行业务逻辑&#xff08;如多次扣款&#xff09;系统资源浪费用户…...

同一子网通信

添加交换机后的通信流程 1. 同一子网内&#xff08;使用交换机&#xff09; 判断是否在同一子网&#xff1a; 主机A通过子网掩码判断主机B的IP地址是否属于同一子网。若在同一子网&#xff0c;主机A需要通过ARP获取主机B的MAC地址。 ARP请求&#xff08;广播&#xff09;&…...

快速迭代:利用 nodemon 和其他工具实现 Express.js 热更新

在开发 Express.js 应用时&#xff0c;热更新&#xff08;Hot Reloading&#xff09;可以显著提升开发效率&#xff0c;因为它允许你在修改代码后立即看到效果&#xff0c;而无需手动重启服务器。以下是几种实现热更新的方法和工具&#xff0c;帮助你在开发过程中更高效地工作。…...

BUG日志:Maven项目启动报错(文件名或者文件扩展名过长)

Bug日志编号&#xff1a;[Maven-001] 标题&#xff1a;Windows系统下Maven项目因路径过长导致命令行执行失败 1. 问题描述 现象&#xff1a;执行mvn clean install时报错&#xff1a; The input line is too long 或 The filename or extension is too long触发条件&#xf…...

IntelliJ IDEA 快捷键系列:重命名快捷键详解

目录 引言一、默认重命名快捷键1. Windows 系统‌2. Mac 系统‌ 二、操作步骤与技巧1. 精准选择重命名范围‌2. 智能过滤无关内容‌ 三、总结 引言 在代码重构中&#xff0c;‌重命名变量、类、方法‌ 是最常用的操作之一。正确使用快捷键可以极大提升开发效率。本文针对 ‌Ma…...

零基础掌握分布式ID生成:从理论到实战的完整指南 [特殊字符]

一、为什么需要分布式ID&#xff1f; &#x1f914; 在单机系统中&#xff0c;使用数据库自增ID就能满足需求。但在分布式系统中&#xff0c;多个服务节点同时生成ID时会出现以下问题&#xff1a; ID冲突&#xff1a;不同节点生成相同ID 扩展困难&#xff1a;数据库自增ID无法…...

使用python反射,实现pytest读取yaml并发送请求

pytest yaml yaml - feature: 用户模块story: 登录title: 添加用户request:method: POSTurl: /system/user/listheaders: nullparams: nullvalidate: nullread_yaml_all def read_yaml_all(path):with open(path, r, encodingutf-8) as f:value yaml.safe_load(f)return v…...

点灯、点各式各样的灯

鱼离水则身枯&#xff0c;心离书则神索。 前言闪灯呼吸灯流水灯二进制数显示灯蜂鸣器节拍流水音乐会总结 前言 上回书咱们简单了解了一点有关特殊功能寄存器sfr、通用输入输出GPIO、位操作运算符sbit和一个不靠单片机上的晶振(拿来定时的)的依托于单片机CPU空操作的ms级延时函…...

Matlab 汽车悬架系统动力学建模与仿真

1、内容简介 略 Matlab 170-汽车悬架系统动力学建模与仿真 可以交流、咨询、答疑 2、内容说明 略 本文对题目给定的1/2汽车四自由度模型&#xff0c;建立状态空间模型进行系统分析&#xff0c;并通过MATLAB仿真对系统进行稳定性、可控可观测性分析&#xff0c;对得的结果进行…...

专访数势科技谭李:智能分析 Agent 打通数据平权的最后一公里

作者|斗斗 编辑|皮爷 出品|产业家 伦敦塔桥下的泰晤士河底&#xff0c;埋藏着工业革命的隐秘图腾——布鲁内尔设计的隧道盾构机。在19世纪城市地下轨道建设的过程中&#xff0c;这个直径11米的钢铁巨兽没有选择拓宽河道&#xff0c;而是开创了地下通行的新维度。 “我们不…...

了解浏览器

本文来自腾讯元宝 Chrome浏览器&#xff08;Google Chrome&#xff09;是由Google开发的一款免费网页浏览器&#xff0c;自2008年发布以来凭借其高效、安全、简洁的特点成为全球市场份额最高的浏览器。以下是其核心信息及最新动态的综合分析&#xff1a; 一、核心优势与技术特点…...

2、操作系统之软件基础

一、硬件支持系统 &#xff0c;系统管理硬件 操作系统核心功能可以分为&#xff1a; 守护者&#xff1a;对硬件和软件资源的管理协调者&#xff1a;通过机制&#xff0c;将各种各样的硬件资源适配给软件使用。 所以为了更好的管理硬件&#xff0c;操作系统引进了软件。其中3大…...

STC89C52单片机学习——第20节: [8-2]串口向电脑发送数据电脑通过串口控制LED

写这个文章是用来学习的,记录一下我的学习过程。希望我能一直坚持下去,我只是一个小白,只是想好好学习,我知道这会很难&#xff0c;但我还是想去做&#xff01; 本文写于&#xff1a;2025.03.15 51单片机学习——第20节: [8-2]串口向电脑发送数据&电脑通过串口控制LED 前言…...

K8S下nodelocaldns crash问题导致域名请求响应缓慢

前言 最近做项目&#xff0c;有业务出现偶发的部署导致响应很慢的情况&#xff0c;据了解&#xff0c;业务使用域名访问&#xff0c;相同的nginx代理&#xff0c;唯一的区别就是K8S重新部署了。那么问题大概率出现在容器平台&#xff0c;毕竟业务是重启几次正常&#xff0c;偶…...

CVPR2024 | TT3D | 物理世界中可迁移目标性 3D 对抗攻击

Towards Transferable Targeted 3D Adversarial Attack in the Physical World 速览总结摘要-Abstract引言-Introduction相关工作-Related Work方法-MethodologyPreliminray-预备知识问题表述-Problem FormulationNeRF参数空间中的双重优化-Dual Optimization in NeRF Paramete…...

全面对比分析:HDMI、DP、DVI、VGA、Type-C、SDI视频接口特点详解

在当今的多媒体时代&#xff0c;视频接口的选择对于设备连接和显示效果至关重要。不同的视频接口在传输质量、兼容性、带宽等方面各有优劣。本文将全面对比分析常用的视频接口HDMI、DP、DVI、VGA、Type-C、SDI&#xff0c;帮助读者更好地理解它们的特点和适用场景。 一、HDMI&…...

传输层自学

传输实体&#xff1a;完成传输层任务的硬件或软件 可能位于&#xff1a; 操作系统内核独立的用户进程绑定在网络应用中的链接库网络接口卡 1.功能&#xff1a; 网络层与传输层作用范围比较&#xff1f; 网络层负责把数据从源机送达到目的机 传输层负责把数据送达到具体的应…...

使用爬虫获取自定义API操作API接口

1. 引言 在现代Web开发中&#xff0c;API&#xff08;应用程序接口&#xff09;是前后端通信的桥梁。通过API&#xff0c;前端可以从后端获取数据&#xff0c;进行各种操作。而爬虫是一种自动化工具&#xff0c;用于从网站上提取数据。本文将详细介绍如何使用爬虫获取自定义AP…...

微服务架构下前端如何配置 OpenAPI 接口

在微服务架构中&#xff0c;后端通常由多个独立的服务组成&#xff0c;每个服务可能提供自己的 API 接口。为了在前端项目中高效地调用这些 API&#xff0c;可以使用 OpenAPI 规范生成客户端代码。以下是详细的配置步骤和最佳实践&#xff1a; 1. 理解 OpenAPI 规范 OpenAPI 是…...

Kotlin知识体系(二) : Kotlin的七个关键特性

前言 在Android开发中&#xff0c;Kotlin以其简洁的语法和强大的特性显著提升了开发效率。本文将解析Kotlin中7个关键特性&#xff0c;通过代码示例展示它们在实际开发中的应用。 一、构造函数&#xff1a;主次分明 主构造函数 class User constructor(_name: String) { //…...

FreeRTOS源码概述

FreeRTOS源码概述 1 FreeRTOS目录结构 使用 STM32CubeMX 创建的 FreeRTOS 工程中&#xff0c;FreeRTOS 相关的源码如下&#xff1a; 主要涉及2个目录&#xff1a; Core Inc 目录下的 FreeRTOSConfig.h 是配置文件Src 目录下的 freertos.c 是 STM32CubeMX 创建的默认任务 Mi…...

日志统计(C++,模拟,双指针)

题目要我们求在某个时间段中&#xff0c;帖子点赞数达到K的帖子数 遍历方式一 我们可以先对所有帖子根据时间&#xff0c;升序排序 枚举每一条帖子&#xff0c;枚举后续每一条帖子&#xff0c;如果id相同且时间差小于d&#xff0c;那么就记录起来&#xff0c;如果记录数量cn…...

加固脱壳技术:DEX动态加载对抗

1. 加固技术原理剖析 1.1 DEX保护演进路线 加固方案发展历程&#xff1a; graph LR A[2015 代码混淆] --> B[2017 DEX动态加载] B --> C[2019 VMP指令虚拟化] C --> D[2022 全链路加密] 1.1.1 主流加固方案对比 厂商核心防护技术弱点分析梆梆加固DEX文件分片…...

C++之list类(超详细)

在上一节中我们学习了STL中的vector这个容器&#xff0c;这节我们来学习一下另外一个常用的容器——list。 文章目录 前言 一、list的介绍 二、list的使用及相关接口 1.list的使用 2.list的迭代器使用 3.list的相关接口 3.1 list capacity 3.2 list element access 3.3…...

强化学习的一些概念

目录 强化学习 打个比方 核心要素 State Action Reward 几个代码demo 学习目标 强化学习 强化学习&#xff08;Reinforcement Learning, RL&#xff09;是机器学习的一个分支&#xff0c;旨在让智能体&#xff08;Agent&#xff09;通过与环境的交互学习最优策略&#xff0c;以…...