交换2个html元素并在其上保留事件侦听器

有类似的问题,但所有的答案都只是针对内部的内容交换html元素。

我需要交换两个具有大量内容(表格,选择框,输入等)的div与元素上的事件监听器等。不破坏所有这些。

我可以访问jQuery 1.5。 所以答案就可以了。

要交换两个div而不丢失事件处理程序或破坏DOM引用,您只需在DOM中移动它们即可。 关键是不要更改innerHTML,因为它会从头开始重新创建新的DOM节点,并且这些DOM对象上的所有先前事件处理程序都会丢失。

但是,如果您只是将DOM元素移动到DOM中的新位置,则所有事件都会保持连接,因为DOM元素仅在不更改DOM元素本身的情况下进行重新分配。

这是一个快速函数,可以交换DOM中的两个元素。 它应该适用于任何两个元素,只要一个元素不是另一个元素的子元素:

function swapElements(obj1, obj2) { // create marker element and insert it where obj1 is var temp = document.createElement("div"); obj1.parentNode.insertBefore(temp, obj1); // move obj1 to right before obj2 obj2.parentNode.insertBefore(obj1, obj2); // move obj2 to right before where obj1 used to be temp.parentNode.insertBefore(obj2, temp); // remove temporary marker node temp.parentNode.removeChild(temp); } 

你可以在这里看到它的工作: http : //jsfiddle.net/jfriend00/NThjN/


这是一个没有插入临时元素的版本:

 function swapElements(obj1, obj2) { // save the location of obj2 var parent2 = obj2.parentNode; var next2 = obj2.nextSibling; // special case for obj1 is the next sibling of obj2 if (next2 === obj1) { // just put obj1 before obj2 parent2.insertBefore(obj1, obj2); } else { // insert obj2 right before obj1 obj1.parentNode.insertBefore(obj2, obj1); // now insert obj1 where obj2 was if (next2) { // if there was an element after obj2, then insert obj1 right before that parent2.insertBefore(obj1, next2); } else { // otherwise, just append as last child parent2.appendChild(obj1); } } } 

工作演示: http : //jsfiddle.net/jfriend00/oq92jqrb/

这是一个更简单的函数,用于交换两个元素而无需实际重新加载元素…

 function swapElements(obj1, obj2) { obj2.nextSibling === obj1 ? obj1.parentNode.insertBefore(obj2, obj1.nextSibling) : obj1.parentNode.insertBefore(obj2, obj1); } 

注意:如果obj1有像YouTube这样的嵌入式video,则在交换时不会重新加载。 这只是元素的位置发生了变化。

如果跟踪两个元素的parentNodes和nextSibling为1,则可以将两个元素与其子元素交换,而不使用任何临时占位符。

如果第二个元素是唯一的子元素,或者是其父元素的最后一个子元素,则将其替换(正确)附加到父元素。

 function swap(a, b){ var p1= a.parentNode, p2= b.parentNode, sib= b.nextSibling; if(sib=== a) sib= sib.nextSibling; p1.replaceChild(b, a); if(sib) p2.insertBefore(a, sib); else p2.appendChild(a); return true; } 

这在某种程度上取决于您的事件如何绑定到您正在交换的元素。 如果您正在使用jQuery,那么这个答案就是您所需要的。

主要的是不deletedelete removeChildnode元素,只是将html复制粘贴到其他地方。 这样做,一些浏览器将清除所有资源(包括事件处理程序),因此绑定事件将丢失。 虽然IE在动态绑定事件方面因泄漏内存而臭名昭着。 很难预测各种浏览器的行为方式。

基本上,我会说:以你喜​​欢的任何方式交换元素,除了复制/粘贴HTML字符串,并使用jQuery的.live()方法绑定你的事件。 因为我不认为1.5有.on方法

我的简单function似乎是最短且最广泛兼容的。 它不需要占位符或重新加载元素或任何杂乱的东西:

 function swapElements(el1, el2) { var p2 = el2.parentNode, n2 = el2.nextSibling if (n2 === el1) return p2.insertBefore(el1, el2) el1.parentNode.insertBefore(el2, el1); p2.insertBefore(el1, n2); } 

由于jQuery被标记在问题中,这里是一个jQuery解决方案:

  $('#el_to_move').appendTo('#target_parent_el'); 

而已。 jQuery会将其剪切/粘贴到新位置。


这也可能有用:

https://api.jquery.com/detach/