You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将现有拖拽交换改为拖拽重排(无第三方库+Grid布局)

实现Grid布局下的拖拽重排功能

基于你现有的代码,我们可以通过直接操作DOM节点来实现拖拽重排,而非交换元素内容。以下是修改后的完整实现:

HTML

<script src="https://kit.fontawesome.com/a26f6e4ee4.js"></script>
<div class="components drag-container">
</div>

CSS

.components{
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(58px, 1fr));
    align-content: baseline;
    gap: 2em;
    padding: 10px;
}

.component{
  gap: 5px;
  max-width: 80px;
  display: flex;
  flex-direction: column;
  justify-content:center;
  align-items:center;
  padding: 10px;
  text-align:center;
  cursor: grab;
  transition: background-color 0.2s ease;
}

.component:hover{
  border: 1px solid gray;
}

.component button{
  width: 30px;
  height: 30px;
}

.draggable-box{
  padding: 4px;
}

.draggable-box.over{
  background-color: rgba(0,0,0,0.1);
  border-radius: 4px;
}

.dragging{
  opacity: 0.4;
  cursor: grabbing;
}

JavaScript

const container = document.querySelector(".drag-container");
const template = `
<div draggable="true" class="draggable-box">
  <div class="component draggable" id="%id%">
    <button>
      <i class="fa-solid fa-lightbulb"></i>
    </button>
    <span>%name%</span>
  </div>
</div>`;
let items, dragSrcEl;

const fillDragContainer = function () {
    for (let i = 0; i < 10; i++) {
        let friendlyIndex = i+1;
        let html = template.replace("%id%", `comp_${friendlyIndex}`).replace("%name%", `Name ${friendlyIndex}`);
        container.insertAdjacentHTML("beforeend", html);
    }
    addEventsToElements();
}

const handleDragStart = function(e) {
    this.classList.add('dragging');
    dragSrcEl = this;
    e.dataTransfer.effectAllowed = 'move';
}

const handleDragEnd = function(e) {
    this.classList.remove('dragging');
    items.forEach(item => item.classList.remove('over'));
}

const handleDragOver = function(e) {
    e.preventDefault();
    e.dataTransfer.dropEffect = 'move';
    return false;
}

const handleDragEnter = function(e) {
    if(this !== dragSrcEl){
        this.classList.add('over');
    }
}

const handleDragLeave = function(e) {
    this.classList.remove('over');
}

const handleDrop = function(e) {
    e.stopPropagation();
    e.preventDefault();

    if (dragSrcEl !== this) {
        const siblings = Array.from(container.children);
        const srcIndex = siblings.indexOf(dragSrcEl);
        const targetIndex = siblings.indexOf(this);

        if(srcIndex < targetIndex){
            container.insertBefore(dragSrcEl, this.nextSibling);
        } else {
            container.insertBefore(dragSrcEl, this);
        }
    }

    this.classList.remove('over');
    return false;
}

const addEventsToElements = function () {
    items = document.querySelectorAll(".draggable-box");
    items.forEach(item => {
        item.addEventListener('dragstart', handleDragStart);
        item.addEventListener('dragend', handleDragEnd);
        item.addEventListener('dragover', handleDragOver);
        item.addEventListener('dragenter', handleDragEnter);
        item.addEventListener('dragleave', handleDragLeave);
        item.addEventListener('drop', handleDrop);
    });
}

fillDragContainer();

关键修改说明

  • DOM节点移动替代内容交换:在handleDrop中通过insertBefore直接移动拖拽的DOM节点,而非交换innerHTML,确保整个元素被重排,Grid布局会自动适配新的元素顺序。
  • 优化视觉反馈:新增.dragging类标记正在拖拽的元素,.over类标记拖拽进入的目标位置,让拖拽状态更直观。
  • 简化事件逻辑:移除冗余的状态变量,精简事件处理逻辑,避免状态混乱。
  • 适配Grid布局:Grid布局会根据子元素顺序自动重排,只需调整DOM节点顺序即可实现流式重排效果。

内容的提问来源于stack exchange,提问作者Dr.Random

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 00:26:40