JavaScript DOM移除元素


198

我正在尝试测试DOM元素是否存在,如果确实存在,则将其删除,如果不存在,则将其创建。

var duskdawnkey = localStorage["duskdawnkey"];
var iframe = document.createElement("iframe");
var whereto = document.getElementById("debug");
var frameid = document.getElementById("injected_frame");
iframe.setAttribute("id", "injected_frame");
iframe.setAttribute("src", 'http://google.com');
iframe.setAttribute("width", "100%");
iframe.setAttribute("height", "400");

if (frameid) // check and see if iframe is already on page
{ //yes? Remove iframe
    iframe.removeChild(frameid.childNodes[0]);
} else // no? Inject iframe
{
    whereto.appendChild(iframe);
    // add the newly created element and it's content into the DOM
    my_div = document.getElementById("debug");
    document.body.insertBefore(iframe, my_div);
}

检查是否存在,创建元素有效,但是删除该元素无效。基本上,所有这些代码所做的就是通过单击按钮将iframe注入网页。我想发生的是,如果iframe已经存在,可以删除它。但是由于某种原因,我失败了。


Answers:


338

removeChild 应该在父级上调用,即:

parent.removeChild(child);

在您的示例中,您应该执行以下操作:

if (frameid) {
    frameid.parentNode.removeChild(frameid);
}

谢谢,在我阅读您的帖子之前就已经弄清楚了。必须将其更改为whereto.removeChild(whereto.childNodes [0]);
约书亚·雷德菲尔德

6
假设您的框架始终是debugdiv 的第一个孩子,那也将起作用。使用parentNode是更通用的解决方案,可以与任何元素一起使用。
卡萨布兰卡2012年

1
该解决方案可能还不够。如果有人在阅读本文,请看看格伦的建议
Sebas 15'30

79

在大多数浏览器中,从DOM中删除元素的方式比调用.removeChild(element)其父元素(调用)要简洁得多element.remove()。在适当的时候,这可能会成为从DOM中删除元素的标准且惯用的方式。

.remove()方法于2011年(commit)添加到DOM Living Standard中,此后已由Chrome,Firefox,Safari,Opera和Edge实施。任何版本的Internet Explorer均不支持该功能。

如果要支持较旧的浏览器,则需要对其进行填充。事实证明,这有点恼人,这是因为似乎没有人制造出包含这些方法的通用DOM填充程序,而且还因为我们不只是将方法添加到单个原型中,而是因为没有将其添加到单个原型中。它是的方法ChildNode,它只是规范定义的接口,JavaScript无法访问,因此我们无法在其原型中添加任何内容。因此,我们需要找到所有从ChildNode浏览器继承并在浏览器中实际定义的原型,并将其添加.remove到其中。

这是我想出的垫片,我已经确认了它在IE 8中的工作原理。

(function () {
    var typesToPatch = ['DocumentType', 'Element', 'CharacterData'],
        remove = function () {
            // The check here seems pointless, since we're not adding this
            // method to the prototypes of any any elements that CAN be the
            // root of the DOM. However, it's required by spec (see point 1 of
            // https://dom.spec.whatwg.org/#dom-childnode-remove) and would
            // theoretically make a difference if somebody .apply()ed this
            // method to the DOM's root node, so let's roll with it.
            if (this.parentNode != null) {
                this.parentNode.removeChild(this);
            }
        };

    for (var i=0; i<typesToPatch.length; i++) {
        var type = typesToPatch[i];
        if (window[type] && !window[type].prototype.remove) {
            window[type].prototype.remove = remove;
        }
    }
})();

这在IE 7或更低版​​本中不起作用,因为在IE 8之前无法扩展DOM原型。我认为,尽管到了2015年,大多数人都不需要关心这些事情。

包含它们的填充程序后,element只需调用以下命令即可从DOM中删除DOM元素

element.remove();

1
只需将其保留在此处:polyfill.io/v2/docs/features/#Element_prototype_remove如果您包括该自动
魔术填充

4
只要您不关心IE,肯定会在2017年做到这一点。请参阅:developer.mozilla.org/en-US/docs/Web/API/ChildNode/remove
nevf

45

似乎我没有足够的代表来发表评论,因此还需要另一个答案。

当使用removeChild()或通过在父对象上设置innerHTML属性来取消链接节点时,还需要确保没有其他引用它的对象,否则它实际上不会被破坏并会导致内存泄漏。在调用removeChild()之前,有很多方法可以获取对节点的引用,并且必须确保明确删除那些未超出范围的引用。

Doug Crockford在这里写道,事件处理程序是IE中循环引用的已知原因,并建议在调用removeChild()之前按如下方式明确删除它们:

function purge(d) {
    var a = d.attributes, i, l, n;
    if (a) {
        for (i = a.length - 1; i >= 0; i -= 1) {
            n = a[i].name;
            if (typeof d[n] === 'function') {
                d[n] = null;
            }
        }
    }
    a = d.childNodes;
    if (a) {
        l = a.length;
        for (i = 0; i < l; i += 1) {
            purge(d.childNodes[i]);
        }
    }
}

即使你采取了很多措施,如通过斯-英戈·法利说明你仍然可以得到内存泄漏在IE 这里

最后,不要陷入认为Java 删除就是答案的陷阱。似乎很多人都建议这样做,但不会做。是了解Kangax 删除的重要参考。


1
也许您可以显示一些jsFiddle来证明这一点。谢谢
Muhaimin 2014年

1
我确认这种行为。我的框架在dom布局上使用Javascript对象映射树。每个js对象都引用其dom元素。即使我呼吁element.parentNode.removeChild删除元素,它们仍然存在并且仍然可以被引用。它们只是在常规dom树中不可见。
塞巴斯2015年

是的,然后删除指向该js映射对象的全局指针可以神奇地解锁垃圾回收器。这是对已接受答案的重要补充。
塞巴斯

11

使用Node.removeChild()可以为您完成这项工作,只需使用如下代码:

var leftSection = document.getElementById('left-section');
leftSection.parentNode.removeChild(leftSection);

在DOM 4中,应用了remove方法,但是根据W3C,浏览器支持不佳:

方法node.remove()在DOM 4规范中实现。但是由于浏览器支持不佳,您不应该使用它。

但是如果您使用jQuery,则可以使用remove方法。

$('#left-section').remove(); //using remove method in jQuery

同样在新的框架中,您可以使用条件来删除元素,例如*ngIf在Angular和React中,根据条件来渲染不同的视图...


如果要使用createElement在js中创建模式节点,则只需确保在删除节点之前检查该节点是否存在。 if(leftSection){..your code}应该可以完成这项工作。
阿夫桑·阿卜杜拉利·古吉拉特

0

如果您乐于使用出色的功能:

$("#foo").remove();

从DOM中完全删除元素。

要删除元素而不删除数据和事件,请改用此方法:

$("#foo").detach();

jQuery文档

.remove()方法将元素从DOM中取出。使用.remove()时要删除它里面的元素本身,以及一切。除了元素本身之外,还删除了所有与元素相关联的绑定事件和jQuery数据。要删除元素而不删除数据和事件,请.detach()改用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.