繁体   English   中英

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

[英]How to remove only the parent element and not its child elements in JavaScript?

让我们说:

<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,但无法理解如何做到这一点。

使用jQuery你可以这样做:

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

快速链接到文档:

  • contents (): jQuery
  • replaceWithcontent :[ String | Element | jQuery ]): jQuery

与库无关的方法是在删除之前插入要在其自身之前删除的元素的所有子节点(隐式地将它们从旧位置移除):

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

nodeToBeRemoved.parentNode.removeChild(nodeToBeRemoved);

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

你应该确保使用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);
 $('.remove-just-this > *').unwrap()

更优雅的方式是

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

使用现代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是扩展运算符,将每个数组元素作为参数传递

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

  1. 在变量中保存对外部div的父级的引用
  2. 将内部div复制到另一个变量。 这可以通过将内部div的innerHTML保存到变量以快速而脏的方式完成,或者可以逐个节点地递归复制内部树。
  3. 使用外部div作为参数调用外部div的父级上的removeChild
  4. 将复制的内部内容插入到外部div的父级中的正确位置。

有些图书馆会为你做一些或所有这些,但上面的内容将在幕后进行。

而且,既然你也尝试过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

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

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)

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

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

我已经在5,000行和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完成。

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

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

将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> 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM