有类似的问题,但所有答案都只针对内部内容交换html元素。
我需要交换两个带有大量内容(表格,选择框,输入等)的div与元素上的事件监听器等。不会破坏所有这些。
我可以访问jQuery 1.5。所以答案就可以了。
答案 0 :(得分:49)
要交换两个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);
}
}
}
答案 1 :(得分:8)
这是一个更简单的函数,用于交换两个元素而无需实际重新加载元素...
function swapElements(obj1, obj2) {
obj2.nextSibling === obj1
? obj1.parentNode.insertBefore(obj2, obj1.nextSibling)
: obj1.parentNode.insertBefore(obj2, obj1);
}
注意:如果obj1有像YouTube这样的嵌入式视频,则在交换时不会重新加载。 这只是元素的位置发生了变化。
答案 2 :(得分:1)
如果你跟踪两个元素的parentNodes和一个的nextSibling,你可以将两个元素与他们的子元素交换,而不需要任何临时占位符。
如果第二个元素是唯一的子元素,或者是其父元素的最后一个子元素,则将其替换(正确)附加到父元素。
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;
}
答案 3 :(得分:0)
这在某种程度上取决于您的事件如何绑定到您正在交换的元素。如果您正在使用jQuery,那么this答案就是您所需要的。
主要的不是delete
或removeChildnode
元素,只是将html复制粘贴到别处。这样做,一些浏览器将清除所有资源(包括事件处理程序),因此绑定事件将丢失。虽然IE在动态绑定事件方面因泄漏内存而臭名昭着。很难预测各种浏览器的行为方式。
基本上,我会说:以你喜欢的任何方式交换元素,除了复制/粘贴HTML字符串,并使用jQuery的.live()
方法绑定你的事件。因为我认为1.5不具有.on
方法
答案 4 :(得分:0)
我的简单功能似乎是最短且最广泛兼容的。它不需要占位符或重新加载元素或类似的任何杂乱:
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);
}
答案 5 :(得分:0)
由于jQuery在问题中被标记,因此这是一个jQuery解决方案:
$('#el_to_move').appendTo('#target_parent_el');
那就是它。 jQuery会将其剪切/粘贴到新位置。
这也可能有所帮助:
答案 6 :(得分:0)
考虑到o1.swapNode(o2);的事实,这一切都很奇怪。可以在IE中运行很长时间。在我的对象和文本节点混合在一起的情况下,仅适用于一种版本(已在此处显示):
let t = document.createElement("div");
o1.parentNode.insertBefore(t, o1);
o2.parentNode.insertBefore(o1, o2);
t.parentNode.insertBefore(o2, t);
t.parentNode.removeChild(t);
是的,我讨厌创建临时节点,但是如果您直接使用它(没有调用函数),则没有此技巧的上述版本将失败。有时您不想调用函数。
答案 7 :(得分:0)
如果彼此相邻交换元素,这真的很容易:
<div class="container">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
</div>
$('.container .item:nth-child(2)').insertBefore('.container .item:nth-child(1)');