拖拽事件开发疑问:如何保留被拖拽元素的初始位置
解决拖拽后元素保留在初始位置的问题
嘿,我看你遇到了拖拽操作后原元素被移走的问题——这其实是因为你当前的代码里直接把元素移动到了目标容器,而不是复制它。咱们来一步步搞定这个问题:
问题根源
你在drag函数里写的document.getElementById("tareas").append(document.getElementById(data));这行代码,会把DOM节点从它原来的父元素中移除,然后添加到#tareas容器里。这就是为什么原位置的元素消失了。要让原元素留在原位,我们需要复制一个元素副本,把副本放到目标容器里。
修正后的完整实现
首先,我们要遵循标准的拖拽事件流程:dragstart(设置拖拽数据)→dragover(允许放置)→drop(处理放置逻辑),而不是把所有逻辑都堆在dragstart里。
1. JavaScript代码
// 拖拽开始时设置数据 function drag(ev) { ev.dataTransfer.setData("text", ev.target.id); } // 允许放置:必须阻止默认行为,否则drop事件不会触发 function allowDrop(ev) { ev.preventDefault(); } // 处理放置逻辑:复制元素并添加到目标容器 function drop(ev) { ev.preventDefault(); // 获取拖拽的元素ID const elementId = ev.dataTransfer.getData("text"); const originalElement = document.getElementById(elementId); // 复制原元素:cloneNode(true)表示深复制(包含子元素和属性) const elementCopy = originalElement.cloneNode(true); // 给副本设置新ID(可选,但避免页面上出现重复ID) elementCopy.id = `${elementId}-copy-${Date.now()}`; // 将副本添加到目标容器 document.getElementById("tareas").append(elementCopy); }
2. 对应的HTML修改
给目标容器#tareas添加ondragover和ondrop事件绑定:
<!-- 目标容器 --> <div id="tareas" ondragover="allowDrop(event)" ondrop="drop(event)"></div> <!-- 可拖拽元素 --> <p id="item1" class="text-danger materias" draggable="true" ondragstart="drag(event)">Cambio aceite</p>
关键说明
cloneNode(true):这个方法会创建原元素的完整副本,包括所有子元素、属性和类名。如果你只需要复制元素本身(不包含子元素),可以用cloneNode(false)。- 阻止默认行为:
dragover和drop事件里必须调用ev.preventDefault(),否则浏览器会执行默认的拖拽行为(比如打开链接),导致我们的自定义逻辑失效。 - 副本ID:给副本设置新ID是个好习惯,避免页面上出现重复的ID,这可能会导致后续DOM操作出问题。
这样修改后,你拖拽元素时,原元素会留在初始位置,同时目标容器里会出现一个一模一样的副本,完全符合你的需求~
内容的提问来源于stack exchange,提问作者Jaime Cuellar




