如何在JavaScript中只删除父元素而不删除其子元素?

时间:2008-10-04 08:46:38

标签: javascript dom

让我们说:

<div>
  pre text
  <div class="remove-just-this">
    <p>child foo</p>
    <p>child bar</p>
    nested text
  </div>
  post text
</div>

到此:

<div>
  pre text
  <p>child foo</p>
  <p>child bar</p>
  nested text
  post text
</div>

我一直在想使用Mootools,jQuery甚至(原始)JavaScript,但无法理解如何做到这一点。

12 个答案:

答案 0 :(得分:129)

使用jQuery可以执行此操作:

var cnt = $(".remove-just-this").contents();
$(".remove-just-this").replaceWith(cnt);

文档的快速链接:

  • contents(): jQuery
  • replaceWith content :[ String | Element | jQuery ]): jQuery的

答案 1 :(得分:36)

独立于库的方法是在删除之前插入要删除的元素的所有子节点(隐式地将它们从旧位置移除):

while (nodeToBeRemoved.firstChild)
{
    nodeToBeRemoved.parentNode.insertBefore(nodeToBeRemoved.firstChild,
                                            nodeToBeRemoved);
}

nodeToBeRemoved.parentNode.removeChild(nodeToBeRemoved);

这会以正确的顺序将所有子节点移动到正确的位置。

答案 2 :(得分:32)

您应该确保使用DOM执行此操作,而不是innerHTML(如果使用jk提供的jQuery解决方案,请确保它移动DOM节点而不是在内部使用innerHTML),为了保存事件处理程序之类的东西。

我的回答很像insin,但对大型结构的效果会更好(单独追加每个节点可能会对重新绘制每个appendChild必须重新应用CSS的问题;对于DocumentFragment,这只会发生一次,因为直到它的子项全部被附加并且它被添加到文档之后它才被显示。

var fragment = document.createDocumentFragment();
while(element.firstChild) {
    fragment.appendChild(element.firstChild);
}
element.parentNode.replaceChild(fragment, element);

答案 3 :(得分:26)

 $('.remove-just-this > *').unwrap()

答案 4 :(得分:17)

更优雅的方式是

$('.remove-just-this').contents().unwrap();

答案 5 :(得分:5)

使用现代JS!

const node = document.getElementsByClassName('.remove-just-this')[0];
node.replaceWith(...node.childNodes); // or node.children, if you don't want textNodes

oldNode.replaceWith(newNode)是有效的ES5

...array是扩展运算符,将每个数组元素作为参数传递

答案 6 :(得分:2)

无论您使用哪个库,都必须在从DOM中删除外部div之前克隆内部div。然后你必须将克隆的内部div添加到外部div所在的DOM中的位置。所以步骤是:

  1. 在变量
  2. 中保存对外部div的父级的引用
  3. 将内部div复制到另一个变量。这可以通过将内部div的innerHTML保存到变量来快速而肮脏地完成,或者您可以逐个节点地递归复制内部树。
  4. 使用外部div作为参数,在外部div的父级上调用removeChild
  5. 将复制的内部内容插入到外部div的父级中的正确位置。
  6. 有些图书馆会为你做一些或所有这些,但上面的内容将在幕后进行。

答案 7 :(得分:2)

而且,既然你也试过mootools,这就是mootools的解决方案。

var children = $('remove-just-this').getChildren();
children.replaces($('remove-just-this');

请注意,这是完全未经测试的,但我之前使用的是mootools,它应该可以使用。

http://mootools.net/docs/Element/Element#Element:getChildren

http://mootools.net/docs/Element/Element#Element:replaces

答案 8 :(得分:0)

如果你想穿着睡衣做同样的事情,这就是它的完成方式。它很棒(谢谢你的眼皮)。由于这个原因,我已经能够制作一个适当的富文本编辑器,可以正确地完成样式而不会搞乱。

def remove_node(doc, element):
    """ removes a specific node, adding its children in its place
    """
    fragment = doc.createDocumentFragment()
    while element.firstChild:
        fragment.appendChild(element.firstChild)

    parent = element.parentNode
    parent.insertBefore(fragment, element)
    parent.removeChild(element)

答案 9 :(得分:0)

在处理重要的DOM时,我一直在寻找最佳答案以性能为导向

eyelidlessness的答案指出,使用javascript表演将是最好的。

我已经在5000行和400,000个字符上进行了以下执行时间测试,其中要删除的部分中有复杂的DOM组合。在使用javascript时,我使用ID而不是类,方便使用。

使用$ .unwrap()

$('#remove-just-this').contents().unwrap();
  

201.237ms

使用$ .replaceWith()

var cnt = $("#remove-just-this").contents();
$("#remove-just-this").replaceWith(cnt);
  

156.983ms

在javascript中使用DocumentFragment

var element = document.getElementById('remove-just-this');
var fragment = document.createDocumentFragment();
while(element.firstChild) {
    fragment.appendChild(element.firstChild);
}
element.parentNode.replaceChild(fragment, element);
  

147.211ms

<强>结论

性能方面,即使在相对较大的DOM结构上,使用jQuery和javascript之间的差异并不大。令人惊讶的是$.unwrap()$.replaceWith()成本最高。 测试已经完成了jQuery 1.12.4。

答案 10 :(得分:0)

如果你正在处理多行,就像在我的用例中那样,你可能会更喜欢这些行:

 $(".card_row").each(function(){
        var cnt = $(this).contents();
        $(this).replaceWith(cnt);
    });

答案 11 :(得分:0)

将div替换为其内容:

const wrapper = document.querySelector('.remove-just-this');
wrapper.outerHTML = wrapper.innerHTML;
<div>
  pre text
  <div class="remove-just-this">
    <p>child foo</p>
    <p>child bar</p>
    nested text
  </div>
  post text
</div>