html 拖拽排序

读者来稿 · song-shao与 batype 的 AI 分身对话整理

·429 字 · 约 1 分钟

在Web开发中,提供给用户一种直观且易于理解的方式来重新组织数据是非常有用的。本文将向您展示如何仅使用原生JavaScript实现一个简单的拖拽排序功能,让用户可以直接在网页上通过拖拽列表项来改变它们的顺序。这种技术常用于待办事项应用、图片库或任何需要手动排序列表项的地方。

基础HTML结构#

首先,我们需要一些基本的HTML结构来承载我们的列表项。这些列表项将是用户可以拖拽的对象。

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>拖拽排序功能</title>
    <style>
      .list {
        width: 100vw;
        margin: 45px auto;
        padding: 0 100px;
        display: block;
        flex-direction: row;
        flex-wrap: wrap;
      }
      .list-item {
        width: 300px;
        height: 100px;
        background-color: #3f67e9;
        border-radius: 12px;
        margin: 10px;
      }

      .list-item.moving {
        bottom: transparent;
        background-color: transparent;
        border: 1px dashed #ccc;
      }
    </style>
  </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>

添加CSS样式#

上面的HTML中已经包含了基本的CSS样式,这些样式定义了列表项的外观以及拖拽状态下的视觉反馈(通过降低透明度来表示正在移动)。

JavaScript拖拽逻辑#

接下来是JavaScript部分,这里我们利用了DOM的拖放API来监听和响应拖拽事件。主要关注以下几个事件处理器:

  • ondragstart:当用户开始拖动某个列表项时触发。
  • ondragenter:当被拖动的元素进入另一个元素的边界时触发。
  • ondragover:当被拖动的元素在另一个元素上方移动时持续触发。
  • ondragend:当用户释放鼠标按钮,结束拖动时触发。
const list = document.querySelector('.list');
let sourceNode = null;

// 当拖动开始时
list.ondragstart = (e) => {
  setTimeout(() => e.target.classList.add('moving'), 0); // 稍后添加移动类
  sourceNode = e.target; // 记录源节点
  e.dataTransfer.effectAllowed = 'move'; // 设置拖动效果
};

// 当拖动进入列表或其子元素时
list.ondragenter = (e) => {
  e.preventDefault(); // 允许放置
  if (e.target !== list && sourceNode !== e.target) {
    const children = [...list.children];
    const sourceIndex = children.indexOf(sourceNode);
    const targetIndex = children.indexOf(e.target);
    if (sourceIndex > targetIndex) {
      list.insertBefore(sourceNode, e.target); // 将源节点插入目标之前
    } else {
      list.insertBefore(sourceNode, e.target.nextElementSibling); // 插入目标之后
    }
    console.log(`从${sourceIndex}移动到${targetIndex}`);
  }
};

// 当拖动悬停时
list.ondragover = (e) => {
  e.preventDefault(); // 默认阻止放置
};

// 当拖动结束时
list.ondragend = (e) => {
  e.target.classList.remove('moving'); // 移除移动类
};

以上就是使用纯JavaScript实现一个简单但功能完整的拖拽排序功能的方法。通过这种方式,你可以让自己的网页变得更加互动且用户友好。希望这份指南能够帮助你在项目中轻松集成这一有用的功能。