如何使用jQuery将子元素从一个父元素移动到另一个父元素?

176
我正在使用jQuery DataTables 插件。我想将搜索框(.dataTables_filter)和每页显示记录数下拉列表(.dataTables_length)从它们的父元素(.dataTables_wrapper)移动到页面上的另一个div中,同时不会丢失任何已注册的JavaScript行为。例如,搜索框有一个附加到“keyup”事件的函数,我希望保持它的完整性。

DOM的结构如下:

<body>
<div id="parent1">
  <div class="dataTables_wrapper" id="table1_wrapper">
    <div class="dataTables_length" id="table1_length">
      <select size="1" name="table1_length">
        <option value="10">10</option>
        <option value="25">25</option>
        <option value="50">50</option>
        <option value="100">100</option>
      </select>
    </div>
    <div class="dataTables_filter" id="table1_filter">
      <input type="text" class="search">
    </div>
    <table id="table1">
    ...
    </table>
  </div>
</div>
<div id="parent2">
  <ul>
    <li><a href="#">Link A</a></li>
    <li><a href="#">Link B</a></li>
    <li><a href="#">Link C</a></li>
  </ul>
</div>
</body>

这是我希望移动后DOM的样子:
<body>
<div id="parent1">
  <div class="dataTables_wrapper" id="table1_wrapper">
    <table id="table1">
    ...
    </table>
  </div>
</div>
<div id="parent2">
  <div class="dataTables_filter" id="table1_filter">
    <input type="text" class="search">
  </div>
  <div class="dataTables_length" id="table1_length">
    <select size="1" name="table1_length">
      <option value="10">10</option>
      <option value="25">25</option>
      <option value="50">50</option>
      <option value="100">100</option>
    </select>
  </div>
  <ul>
    <li><a href="#">Link A</a></li>
    <li><a href="#">Link B</a></li>
    <li><a href="#">Link C</a></li>
  </ul>
</div>
</body>

我一直在研究.append()、.appendTo()、.prepend()和.prependTo()函数,但在实践中没有什么进展。我也看过.parent()和.parents()函数,但好像无法编写可行的解决方案。我还考虑过更改CSS,使元素绝对定位,但坦白地说,页面上有许多流体元素,我真的希望这些元素可以在它们的新父级中浮动。
非常感谢您的任何帮助。

你列出的所有DOM操作函数应该都可以正常工作。将DOM元素附加到另一个父元素会将其移动到新位置,保持所有事件不变。你具体遇到了什么问题?是否有错误? - Anurag
4个回答

378

由于Jage的答案会彻底删除元素,包括事件处理程序和数据,我正在添加一个简单的解决方案,不会这样做,感谢detach函数。

var element = $('#childNode').detach();
$('#parentNode').append(element);

编辑:

在下面的评论中,Igor Mukhin提出了一个更短的版本:

$("#childNode").detach().appendTo("#parentNode");

8
这是最佳解决方案,因为detach() + append() 不会克隆元素,而是将其移动到新位置。这样事件和相关数据就不会丢失了。 - Denes Papp
3
这应该被标记为答案。 - Daniel
69
更简洁的写法:$("#childNode").appendTo("#parentNode"); - Igor Mukhin
我一直使用iimuhin的答案。简单、干净。 - jchwebdev
8
除了不需要分离之外,可以参考我的下面的回答。 - JackArbiter
2
@JackArbiter - detach 对我很有用,因为我需要暂时将子元素从父元素中移除以进行处理,然后再将它们放回原来的父元素中(CPS风格),所以虽然在问题的实例中(从父亲到收养父母),它并不实用,但它确实解决了我的问题 ;) - Campbeln

177

分离是不必要的。

答案(截至2013年)很简单:

$('#parentNode').append($('#childNode'));
根据http://api.jquery.com/append/,您还可以选择页面上的一个元素并将其插入到另一个元素中: $('.container').append($('h2'));
如果以这种方式选择的元素被插入到DOM中的其他单个位置,则它将被移动到目标位置(而不是克隆)。

4
我发现在旧版浏览器中(如IE甚至Edge),detach方法会产生不同的行为。例如,如果父元素被detach并附加到其他元素上,那么Bootstrap的DateTimePicker就无法正常工作,但是仅使用append()方法移动元素可以让DateTimePicker正常运作。 - geekinit

48

$('#parent2').prepend($('#table1_length')).prepend($('#table1_filter'));

如果这段代码对你无效,我认为它应该有效...


这是一个命名问题。我的上面的例子运行良好。字段的实际ID中有多个“-”和“_”,我没有选择该元素,因为ID不匹配。谢谢。 - Dom

36

基于给出的答案,我决定快速制作一个插件来实现此目的:

(function($){
    $.fn.moveTo = function(selector){
        return this.each(function(){
            var cl = $(this).clone();
            $(cl).appendTo(selector);
            $(this).remove();
        });
    };
})(jQuery);

用法:

$('#nodeToMove').moveTo('#newParent');

8
这个方法不会移动元素,而是复制它们。具体来说,如果您在moveTo调用之前已经将元素存储在变量$('#nodeToMove')中,则此方法将不再起作用。 - Roberto
@Jage 为什么不使用 JQuery 语法?$('#nodeToMove').appendTo('#newParent'); http://api.jquery.com/appendto/ - Randall Flagg

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