2012-01-12 180 views
136

我想要測試一個DOM元素是否存在,如果存在,請刪除它,如果它不存在,請創建它。JavaScript 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已經在那裏刪除它。但由於某種原因,我失敗了。

+0

可能重複的[JavaScript:刪除元素的id](http://stackoverflow.com/questions/3387427/javascript-remove-element-by-id) – Zaz 2014-12-30 17:34:13

回答

253

removeChild應在父被調用,即:

parent.removeChild(child); 

在你的榜樣,你應該做的是這樣的:

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

感謝figured它在我閱讀你的文章之前就已經出來了。必須將其更改爲whereto.removeChild(whereto.childNodes [0]); – 2012-01-12 06:18:21

+6

這也可以工作,假設你的框架始終是'debug' div的第一個孩子。使用'parentNode'是一個更通用的解決方案,可以處理任何元素。 – casablanca 2012-01-12 06:19:24

+1

該解決方案可能不夠。如果有人正在閱讀本文,請看看Glenn的建議 – Sebas 2015-07-30 03:42:13

37

好像我沒有足夠的代表張貼評論,所以另一個答案將不得不做。

當您使用removeChild()或通過在父級上設置innerHTML屬性來取消鏈接節點時,還需要確保沒有其他引用它的內容,否則它將不會被銷燬並導致內存泄漏。在調用removeChild()之前,有很多方法可以引用節點,並且必須確保那些未超出範圍的引用被明確刪除。

道格·克羅克福德寫道: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]); 
     } 
    } 
} 

即使你採取了很多預防措施,你可以之前如下如Jens-Ingo Farley here所述,仍然會在IE中發生內存泄漏。

最後,不要陷入思考的陷阱,那就是Javascript 刪除就是答案。這似乎是很多人提出的建議,但不會完成這項工作。 Here是由Kangax瞭解刪除的很好的參考。

+1

,也許你可以展示一些jsFiddle來證明這一點。謝謝 – Muhaimin 2014-02-27 10:51:23

+1

我確認了這種行爲。我的框架在dom佈局上使用了一個Javascript對象映射樹。每個js對象引用它的dom元素。即使我調用'element.parentNode.removeChild'來移除元素,它們仍然活着並且仍然可以被引用。它們只是在常規的dom樹中不可見。 – Sebas 2015-07-30 03:25:16

+0

是的,然後刪除指向該js映射對象的全局指針奇蹟般地解鎖垃圾收集器。這是接受答案的重要補充。 – Sebas 2015-07-30 03:41:27

39

在大多數瀏覽器中,從父節點上調用.removeChild(element)的DOM中刪除元素的方法稍微簡潔一些,這就是調用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; 
     } 
    } 
})(); 

由於extending DOM prototypes isn't possible before IE 8這不適用於IE 7或更低版​​本。不過,我認爲,在2015年的大部分時間裏,大多數人不需要關心這樣的事情。

一旦你已經列入他們的墊片,你就可以從DOM中刪除一個DOM元素element通過簡單地調用

element.remove(); 
+1

只要在這裏:https://polyfill.io/v2/docs/features/#Element_prototype_remove如果你包含automagic polyfill服務,你將得到支持回到IE 7。 – complistic 2016-08-01 00:39:57

+2

這絕對是在2017年做到這一點的方式只要你不關心IE。請參閱:https://developer.mozilla.org/en-US/docs/Web/API/ChildNode/remove – nevf 2017-05-31 21:37:29

1

使用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和反應,使不同的意見,取決於條件...