【问题标题】:JavaScript DOM remove elementJavaScript DOM 删除元素
【发布时间】:2022-12-31 04:32:57
【问题描述】:

我正在尝试测试 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 已经在那里删除它。但由于某种原因,我失败了。

【问题讨论】:

标签: javascript dom


【解决方案1】:

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

parent.removeChild(child);

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

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

【讨论】:

  • 谢谢,在我阅读您的帖子之前就想通了。必须将其更改为 where to.removeChild(where to.childNodes[0]);
  • 假设您的框架始终是 debug div 的第一个子项,这也可以工作。使用parentNode 是一种更通用的解决方案,适用于任何元素。
  • 此解决方案可能还不够。如果有人正在读这篇文章,请看看格伦的建议
【解决方案2】:

在大多数浏览器中,有一种从 DOM 中删除元素的方法比在其父元素上调用 .removeChild(element) 更简洁,也就是调用 element.remove()。在适当的时候,这可能会成为从 DOM 中删除元素的标准和惯用方式。

.remove() 方法于 2011 年添加到 DOM Living Standard (commit),此后已被 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 或更低版本中不起作用,因为 extending DOM prototypes isn't possible before IE 8。不过,我认为,在 2015 年即将到来之际,大多数人不需要关心这些事情。

一旦你包含了它们,你就可以通过简单地调用从 DOM 中删除一个 DOM 元素element

element.remove();

【讨论】:

【解决方案3】:

似乎我没有足够的代表发表评论,所以必须有另一个答案。

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

Doug Crockford 写道 here 已知事件处理程序是 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 中遇到内存泄漏,正如 Jens-Ingo Farley here 所描述的那样。

最后,不要陷入认为 Javascript删除是答案。它似乎被许多人建议,但不会完成这项工作。 Here 是一个很好的理解参考删除由 Kangax 提供。

【讨论】:

  • 也许你可以展示一些 jsFiddle 来证明这一点。谢谢
  • 我确认这种行为。我的框架在 dom 布局上使用 Javascript 对象映射树。每个 js 对象引用它的 dom 元素。即使我调用element.parentNode.removeChild 来删除元素,它们仍然存在并且仍然可以被引用。它们只是在常规的 dom 树中不可见。
  • 是的,然后删除指向该 js 映射对象的全局指针会神奇地解锁垃圾收集器。这是对已接受答案的重要补充。
【解决方案4】:

使用节点.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

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

【讨论】:

  • 如果您使用 createElement 在 js 中创建模态节点,那么只需确保在删除节点之前检查该节点是否存在。if(leftSection){ ..你的代码 }应该做的工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-08
  • 2011-08-28
  • 1970-01-01
  • 2011-01-04
  • 1970-01-01
  • 2014-09-01
相关资源
最近更新 更多