是否有一个原生的jQuery函数来切换元素?

jua*_*uan 168 javascript jquery swap

我可以轻松地用jQuery交换两个元素吗?

如果可能的话,我希望用一行来做这件事.

我有一个选择元素,我有两个按钮可以向上或向下移动选项,我已经选择了目标选择器,我用if做了,但我想知道是否有更简单的方法.

lot*_*tif 228

我找到了一种有趣的方法来解决这个问题,只使用jQuery:

$("#element1").before($("#element2"));
Run Code Online (Sandbox Code Playgroud)

要么

$("#element1").after($("#element2"));
Run Code Online (Sandbox Code Playgroud)

:)

  • 这不会交换两个元素,除非这两个元素紧挨着彼此. (196认同)
  • 我最喜欢这个选项!简单而且兼容性很好.尽管我喜欢使用el1.insertBefore(el2)和el1.insertAfter(el2)来提高可读性. (12认同)
  • 这不应该是接受的答案.它在一般情况下不起作用. (12认同)
  • 虽然有一个旁注..(我想这适用于本页面上的所有解决方案),因为我们在这里操作DOM.当您正在移动的元素中存在iframe时,删除和添加不起作用.iframe将重新加载.此外,它将重新加载到它的原始网址而不是当前网址.非常讨厌但与安全有关.我还没有找到解决方案 (6认同)
  • 是的,这应该有效:文档说:"如果以这种方式选择的元素插入其他地方,它将在目标(未克隆)之前移动". (2认同)
  • 这仅在元素彼此相邻时交换元素,否则 Paolo 的答案是正确的。 (2认同)

bob*_*nce 75

保罗是对的,但我不确定他为什么克隆有关的元素.这不是必需的,并且会丢失与元素及其后代关联的任何引用或事件侦听器.

这是一个使用普通DOM方法的非克隆版本(因为jQuery实际上没有任何特殊的功能来使这个特定的操作更容易):

function swapNodes(a, b) {
    var aparent = a.parentNode;
    var asibling = a.nextSibling === b ? a : a.nextSibling;
    b.parentNode.insertBefore(a, b);
    aparent.insertBefore(b, asibling);
}
Run Code Online (Sandbox Code Playgroud)

  • 啊,有一个角落的情况下,下一个兄弟是b本身.修复了上面的代码片段.jQuery做的完全一样. (3认同)
  • http://docs.jquery.com/Clone - 传递它"true"也克隆事件.我尝试没有先克隆它,但它正在做你现在的事情:它用第二个交换第一个,然后保留第一个. (2认同)
  • 我觉得你应该添加一个 jQuery 版本来在技术上满足这个问题的标题。:) (2认同)

Pao*_*ino 66

不,没有,但你可以鞭打一个:

jQuery.fn.swapWith = function(to) {
    return this.each(function() {
        var copy_to = $(to).clone(true);
        var copy_from = $(this).clone(true);
        $(to).replaceWith(copy_from);
        $(this).replaceWith(copy_to);
    });
};
Run Code Online (Sandbox Code Playgroud)

用法:

$(selector1).swapWith(selector2);
Run Code Online (Sandbox Code Playgroud)

请注意,这仅适用于选择器每个只匹配1个元素的情况,否则会产生奇怪的结果.

  • 是否有必要克隆它们? (2认同)
  • @Ed Woodcock如果你这样做,你将失去对我非常肯定的那些元素的约束事件. (2认同)
  • 当div不是彼此相邻时工作得很好:) (2认同)

小智 37

这个问题存在许多边缘情况,这些问题不是由接受的答案或bobince的答案处理的.涉及克隆的其他解决方案正在走上正轨,但克隆是昂贵且不必要的.我们很想克隆,因为如何交换两个变量的古老问题,其中一个步骤是将一个变量分配给一个临时变量.在这种情况下,不需要分配(克隆).这是一个基于jQuery的解决方案:

function swap(a, b) {
    a = $(a); b = $(b);
    var tmp = $('<span>').hide();
    a.before(tmp);
    b.before(a);
    tmp.replaceWith(b);
};
Run Code Online (Sandbox Code Playgroud)

  • 这应该是公认的答案.克隆会删除任何事件触发器,而不是必需的.我在我的代码中使用了这个确切的方法. (7认同)
  • 这是更好的答案!我碰巧有一个 ul 作为我交换元素的子元素,它是一个 jquery 可排序元素。在与 Paolo Bergantino 的答案交换后,列表项不能再被删除。有了 user2820356 的回答,一切仍然正常。 (3认同)

rob*_*rob 18

对于一般情况,这些答案中的许多答案都是错误的,如果它们实际上工作,则其他答案会不必要地复杂化.jQuery .before.after方法完成了你想要做的大部分工作,但你需要第三个元素,就像许多交换算法的工作方式一样.这很简单 - 当你移动东西时,将一个临时DOM元素作为占位符.没有必要看看父母或兄弟姐妹,当然也没有必要克隆......

$.fn.swapWith = function(that) {
  var $this = this;
  var $that = $(that);

  // create temporary placeholder
  var $temp = $("<div>");

  // 3-step swap
  $this.before($temp);
  $that.before($this);
  $temp.after($that).remove();

  return $this;
}
Run Code Online (Sandbox Code Playgroud)

1)temp之前放临时divthis

2)this之前搬家that

3)that之后移动temp

3b)删除 temp

然后简单

$(selectorA).swapWith(selectorB);
Run Code Online (Sandbox Code Playgroud)

演示:http://codepen.io/anon/pen/akYajE

  • 这是最好的答案,所有其他假定元素都彼此相邻。这在任何情况下都有效。 (2认同)

Mat*_*son 11

你不应该需要两个克隆,一个会做.以Paolo Bergantino为例,我们有:

jQuery.fn.swapWith = function(to) {
    return this.each(function() {
        var copy_to = $(to).clone(true);
        $(to).replaceWith(this);
        $(this).replaceWith(copy_to);
    });
};
Run Code Online (Sandbox Code Playgroud)

应该更快.传递两个元素中较小的元素也应该加快速度.

  • 这个和Paolo的问题在于,他们不能用ID交换元素,因为ID必须是唯一的,因此克隆不起作用.Bobince的解决方案在这种情况下确实有效. (4认同)

Eri*_*nke 7

我之前使用过这样的技术.我将它用于http://mybackupbox.com上的连接器列表

// clone element1 and put the clone before element2
$('element1').clone().before('element2').end();

// replace the original element1 with element2
// leaving the element1 clone in it's place
$('element1').replaceWith('element2');
Run Code Online (Sandbox Code Playgroud)