有类似的问题,但所有的答案都是为了只为里面的内容交换 html 元素。
我需要交换两个 div,其中包含很多内容(表格、选择框、输入等)。元素上有事件监听器,所以我需要在交换主 div 后保留它们。
我可以访问 jQuery 1.5。所以答案是可以的。
有类似的问题,但所有的答案都是为了只为里面的内容交换 html 元素。
我需要交换两个 div,其中包含很多内容(表格、选择框、输入等)。元素上有事件监听器,所以我需要在交换主 div 后保留它们。
我可以访问 jQuery 1.5。所以答案是可以的。
要在不丢失事件处理程序或破坏 DOM 引用的情况下交换两个 div,只需在 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 这样的嵌入视频,则在交换时不会重新加载。只是元素的位置发生了变化。
如果您跟踪两个元素的 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;
}
我的简单功能似乎是最短和最广泛兼容的。它不需要占位符或重新加载元素或任何类似的混乱:
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,那么这个答案就是您所需要的,真的。
最主要的不是元素delete
,removeChildnode
而是将html复制粘贴到其他地方。这样做时,某些浏览器会清除所有资源(包括事件处理程序),因此绑定的事件将丢失。尽管 IE 在动态绑定事件方面因泄漏内存而臭名昭著。真的很难预测各种浏览器的行为方式。
基本上,我会说:以任何你喜欢的方式交换元素,除了复制/粘贴 HTML 字符串,并使用 jQuery 的.live()
方法绑定你的事件。因为我不认为 1.5 有.on
方法
由于 jQuery 在问题中被标记,这里是一个 jQuery 解决方案:
$('#el_to_move').appendTo('#target_parent_el');
而已。jQuery 会将其剪切/粘贴到新位置。
这也可能会有所帮助:
考虑到 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);
是的,我讨厌创建临时节点,但是如果你直接使用它(没有调用函数),没有这个技巧的上述版本会失败。有时您不想调用函数。
如果您要交换彼此相邻的元素,这真的很容易:
<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)');