JavaScript在DOM中移动元素

120

假设我在页面上有三个 <div> 元素。如何交换第一个和第三个 <div> 的位置?使用 jQuery 可以实现。

7个回答

202

这样一个琐碎的任务没有必要使用库:

var divs = document.getElementsByTagName("div");   // order: first, second, third
divs[2].parentNode.insertBefore(divs[2], divs[0]); // order: third, first, second
divs[2].parentNode.insertBefore(divs[2], divs[1]); // order: third, second, first

这里考虑了一个事实,即 getElementsByTagName 返回的是一个实时更新的 NodeList,它会自动根据 DOM 中元素的操作顺序进行更新。

另外,您也可以使用:

var divs = document.getElementsByTagName("div");   // order: first, second, third
divs[0].parentNode.appendChild(divs[0]);           // order: second, third, first
divs[1].parentNode.insertBefore(divs[0], divs[1]); // order: third, second, first

如果你想尝试,还有许多其他可能的排列组合:

divs[0].parentNode.appendChild(divs[0].parentNode.replaceChild(divs[2], divs[0]));

例如 :-)


18
没错,但很难否认像jQuery这样的工具提供了优雅和易读性——更不用提开箱即用的增强功能了。 - Crazy Joe Malloy
13
是的,但是谁只做这一件事呢? - tvanfosson
43
@所有人:原问题询问如何在一个有三个div的页面上交换第三个和第一个div。这就是我回答的问题。如果楼主有更复杂的问题,他们应该提出来,然后就会得到更复杂的答案;-) - NickFitz
2
这会破坏那些元素附加的事件处理程序吗? - Martin
34
如果有人在2014年寻找此内容,请参考这个答案。当时jQuery很有用,但现在不太有用了,因为浏览器已经标准化,所以没有必要添加一个80 kb的库来完成简单的任务。另外,在没有使用jQuery的情况下尝试一下,你才能真正了解什么是DOM :) - gustavohenke
显示剩余6条评论

119

使用jQuery很简单。

$('#div1').insertAfter('#div3');
$('#div3').insertBefore('#div2');

如果您想重复执行此操作,您需要使用不同的选择器,因为当

移动时,它们将保留其ID。

$(function() {
    setInterval( function() {
        $('div:first').insertAfter($('div').eq(2));
        $('div').eq(1).insertBefore('div:first');
    }, 3000 );
});

1
@Ionut -- 关键在于它取决于元素的相对位置。一旦您更改了顺序,您就无法通过它们的id找到第一个和第三个,并且需要找到另一种方法。我的答案只是为了说明实现所需任务的方法的功能,而不是交换集合中第一个和第三个div的全面解决方案。 - tvanfosson
大家好,一个快速的问题:在上述jQuery函数完成后是否有一种简单的方法可以将DOM重置回原始状态? - Vikita
@Vikita - 是的,保存原始的HTML代码然后恢复它。如果处理程序直接应用而不是委派给更高的元素,则可能需要重新应用它们。例如:var html = $('#container').html(); ...; $('#container').html(html); - tvanfosson

83

.before 和 .after

使用现代原生 JS!比以前更好/更干净。无需引用父元素。

const div1 = document.getElementById("div1");
const div2 = document.getElementById("div2");
const div3 = document.getElementById("div3");

div2.after(div1);
div2.before(div3);

所有现代浏览器都受支持!

浏览器支持情况


暂时还不支持Internet Explorer。 - pyronaur
22
为了支持那些使用老旧浏览器或不符合标准的浏览器的用户,你不应该写难以维护的代码。除非你在企业领域工作,否则很少有用户会错过这些功能。 - Gibolt
其他方法在可维护性方面同样有效,尤其是在封装一个漂亮干净的函数时。我支持编写现代化的代码,但这是前沿技术。了解未来的发展方向很棒,但是尽管我不喜欢任何与IE相关的东西——了解你的决策对应用程序的影响很重要。在这种情况下,在任何IE浏览器中都会导致Web应用程序崩溃。如果您可以接受这一点——太好了!我添加了此注释只是为了通知任何通过Google搜索此内容的人 :) - pyronaur
2
27%的用户是“一些用户”吗?我们谈论的是数百万! - SandRock
12
明年这个数字将更接近于10%。主要是企业,政府和老旧移动设备。这通常意味着非个人设备或技术能力较弱的用户。回答应该具有前瞻性,以便我们不会停留在2009年的开发水平。 - Gibolt
6
在现在,微软不再支持IE(尽管我相信它仍然会让开发者在睡梦中受到困扰),因此这是最好且最容易遵循的答案 :) - wickywills

12
jQuery.fn.swap = function(b){ 
    b = jQuery(b)[0]; 
    var a = this[0]; 
    var t = a.parentNode.insertBefore(document.createTextNode(''), a); 
    b.parentNode.insertBefore(a, b); 
    t.parentNode.insertBefore(b, t); 
    t.parentNode.removeChild(t); 
    return this; 
};

并且像这样使用:

$('#div1').swap('#div2');

如果您不想使用jQuery,您可以轻松地调整该函数。

5
var swap = function () {
    var divs = document.getElementsByTagName('div');
    var div1 = divs[0];
    var div2 = divs[1];
    var div3 = divs[2];

    div3.parentNode.insertBefore(div1, div3);
    div1.parentNode.insertBefore(div3, div2);
};

这个函数可能看起来很奇怪,但它严重依赖标准才能正常运行。实际上,它似乎比tvanfosson发布的jQuery版本更好地执行了交换,后者只执行了两次。

它依赖于哪些标准特性?

insertBefore 在现有子节点refChild之前插入节点newChild。如果refChild为null,则在子节点列表末尾插入newChild。 如果newChild是DocumentFragment对象,则所有子节点都按相同顺序在refChild之前插入。如果newChild已经在树中,则首先将其删除。


0

抱歉顶了这个帖子。 我遇到了“交换 DOM 元素”的问题并进行了一些尝试

结果是一个 jQuery 原生的“解决方案”,看起来非常漂亮(不幸的是,我不知道在执行此操作时 jQuery 内部发生了什么)

代码:

$('#element1').insertAfter($('#element2'));

jQuery文档中提到insertAfter()方法移动元素而不是克隆它。

0

在顶部提到的JQuery方法是可行的。 您还可以使用JQuery和CSS。例如,在Div one上应用了class1,在div2上应用了class2(例如,每个CSS类在浏览器上提供特定位置),现在您可以使用jQuery或JavaScript交换类(这将更改位置)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接