如何使用JavaScript实现拖拽排序功能?

46 min read

可以使用以下步骤来实现JavaScript拖拽排序:

  1. 给每个排序元素添加 draggable 属性,以便将元素标记为可拖动。
  2. 通过选择器或 DOM 操作,获取需要排序的元素列表。
  3. 在每个元素上添加 dragstartdragover 事件监听器。
  4. dragstart 监听器中,设置拖动数据,以便在拖动过程中保存排序元素的位置和信息。
  5. dragover 监听器中,防止浏览器默认的拖动行为,并使用 insertBefore 方法调整元素顺序,使其与所拖动的元素相应地改变位置。
  6. dragend 监听器中,更新排序数据,将排序结果传递给后台或保存到本地存储中。

以下是一个可拖拽排序的示例代码:

<ul id="sortable-list">
  <li draggable="true">Item 1</li>
  <li draggable="true">Item 2</li>
  <li draggable="true">Item 3</li>
  <li draggable="true">Item 4</li>
  <li draggable="true">Item 5</li>
</ul>
const list = document.querySelector('#sortable-list');
let dragStartIndex;

// 设置拖动数据
function handleDragStart(e) {
  dragStartIndex = +this.dataset.index;
  e.dataTransfer.setData('text/plain', this.innerHTML);
}

// 阻止浏览器默认的拖动行为,并调整元素位置
function handleDragOver(e) {
  e.preventDefault();
  this.classList.add('over');

  const dragOverIndex = +this.dataset.index;
  const items = Array.from(list.querySelectorAll('li'));

  const dragItem = items[dragStartIndex];
  const dragOverItem = items[dragOverIndex];

  // 在拖动元素上方插入占位符
  if (dragStartIndex < dragOverIndex) {
    this.insertBefore(dragItem, dragOverItem.nextSibling);
  } else {
    this.insertBefore(dragItem, dragOverItem);
  }

  // 更新元素索引
  items.forEach((item, i) => {
    item.dataset.index = i;
  });
}

// 清除样式
function handleDragLeave(e) {
  this.classList.remove('over');
}

// 更新排序数据
function handleDragEnd(e) {
  this.classList.remove('over');
  const items = Array.from(list.querySelectorAll('li'));
  const newOrder = items.map(item => item.innerHTML);
  console.log(newOrder); // 更新后的排序数据
}

// 添加拖动事件监听器
const items = Array.from(list.querySelectorAll('li'));
items.forEach((item, i) => {
  item.dataset.index = i;
  item.addEventListener('dragstart', handleDragStart);
  item.addEventListener('dragover', handleDragOver);
  item.addEventListener('dragleave', handleDragLeave);
  item.addEventListener('dragend', handleDragEnd);
});