JavaScript DOM 移除元素
Posted
技术标签:
【中文标题】JavaScript DOM 移除元素【英文标题】:JavaScript DOM remove element 【发布时间】:2012-02-08 11:48:07 【问题描述】:我正在尝试测试一个 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: remove element by id 的可能重复项 【参考方案1】:在大多数浏览器中,有一种从 DOM 中删除元素的方法比在其父级上调用 .removeChild(element)
更简洁,即只调用 element.remove()
。在适当的时候,这可能会成为从 DOM 中删除元素的标准和惯用方式。
.remove()
方法于 2011 年被添加到 DOM 生活标准 (commit) 中,此后已由 Chrome、Firefox、Safari、Opera 和 Edge 实现。任何版本的 Internet Explorer 都不支持它。
如果您想支持旧版浏览器,则需要对其进行填充。事实证明这有点烦人,因为似乎没有人制作包含这些方法的通用 DOM shim,而且因为我们不只是将方法添加到单个原型中;它是ChildNode
的一个方法,它只是一个规范定义的接口,JavaScript 无法访问,所以我们不能在它的原型中添加任何东西。所以我们需要找到所有继承自ChildNode
并且在浏览器中实际定义的原型,并在其中添加.remove
。
这是我想出的 shim,我已经确认它在 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 年的边缘,大多数人不需要关心这些事情。
添加 shim 后,您只需调用即可从 DOM 中删除 DOM 元素 element
element.remove();
【讨论】:
把这个留在这里:polyfill.io/v2/docs/features/#Element_prototype_remove 如果你包含自动填充服务,你将获得对 IE 7 的支持。 这绝对是2017年的做法,只要你不关心IE。见:developer.mozilla.org/en-US/docs/Web/API/ChildNode/remove【参考方案2】:使用 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
同样在新框架中,您可以使用条件来删除元素,例如 Angular 和 React 中的 *ngIf
,根据条件呈现不同的视图...
【讨论】:
如果您在 js 中使用 createElement 创建模态节点,则只需确保在删除节点之前检查该节点是否存在。 if(leftSection) ..your code 应该可以完成这项工作。【参考方案3】:removeChild
应该在父级上调用,即:
parent.removeChild(child);
在您的示例中,您应该执行以下操作:
if (frameid)
frameid.parentNode.removeChild(frameid);
【讨论】:
感谢在我阅读您的帖子之前就知道了。不得不把它改成 whereto.removeChild(whereto.childNodes[0]); 假设您的框架始终是debug
div 的第一个孩子,这也可以工作。使用parentNode
是一种更通用的解决方案,适用于任何元素。
这个解决方案可能还不够。如果有人正在阅读此内容,请查看 Glenn 的建议【参考方案4】:
似乎我没有足够的代表发表评论,所以必须做另一个答案。
当您使用 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 delete 就是答案的陷阱。它似乎被许多人建议,但不会完成这项工作。 Here 是了解 Kangax delete 的一个很好的参考。
【讨论】:
也许你可以展示一些 jsFiddle 来证明这一点。谢谢 我确认了这种行为。我的框架在 dom 布局上使用了 Javascript 对象映射树。每个 js 对象都引用它的 dom 元素。即使我调用element.parentNode.removeChild
删除元素,它们仍然存在并且仍然可以被引用。它们只是在常规 dom 树中不可见。
是的,然后移除指向那个 js 映射对象的全局指针会神奇地解锁垃圾收集器。这是对已接受答案的重要补充。以上是关于JavaScript DOM 移除元素的主要内容,如果未能解决你的问题,请参考以下文章