2012-01-12 17 views
136

Próbuję przetestować, czy element DOM istnieje, a jeśli istnieje, usuń go, a jeśli nie istnieje, utwórz go.JavaScript DOM usuń element

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); 
} 

Sprawdzanie, czy istnieje, działa, tworzenie elementu działa, ale usunięcie elementu nie. Zasadniczo cały ten kod polega na wstrzyknięciu elementu iframe na stronę internetową poprzez kliknięcie przycisku. To, co chciałbym się wydarzyć, to to, czy element iframe już tam jest, aby go usunąć. Ale z jakiegoś powodu zawodzę.

+0

możliwy duplikat [JavaScript: usuń element według identyfikatora] (http://stackoverflow.com/questions/3387427/javascript-remove-element-by-id) – Zaz

Odpowiedz

253

removeChild powinny być powoływane na rodzica, czyli:

parent.removeChild(child); 

W przykładzie, należy robić coś takiego:

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

Dzięki, to tuż przed przeczytaniem twojego postu. Musiał zmienić go na whereto.removeChild (whereto.childNodes [0]); –

+6

To również działa, zakładając, że twoja ramka jest zawsze pierwszym dzieckiem div 'debugowania '. Używanie 'parentNode' jest bardziej ogólnym rozwiązaniem, które będzie działać z każdym elementem. – casablanca

+1

To rozwiązanie może nie wystarczyć. Jeśli ktoś czyta to, proszę spojrzeć na sugestię Glenna: – Sebas

37

Wydaje się, że nie ma wystarczającej ilości rep aby umieścić komentarz, więc inna odpowiedź będzie musiała zrobić.

Po odłączeniu węzła za pomocą metody removeChild() lub przez ustawienie właściwości innerHTML na obiekcie nadrzędnym należy również upewnić się, że nie ma w nim nic innego, ponieważ w przeciwnym razie nie zostanie ona faktycznie zniszczona i doprowadzi do utraty pamięci nieszczelność. Istnieje wiele sposobów, dzięki którym mógłbyś odwołać się do węzła przed wywołaniem metody removeChild() i musisz upewnić się, że odwołania, które nie wykroczyły poza zakres, zostały jawnie usunięte.

Doug Crockforda pisze here że obsługi zdarzeń są znane przyczyny kołowych odniesień w IE i proponuje ich usunięcie jawnie jak następuje przed wywołaniem 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]); 
     } 
    } 
} 

a nawet jeśli wziąć dużo ostrożności można nadal dostaję wycieki pamięci w IE, jak to opisał Jens-Ingo Farley here.

I na koniec, nie wpadnij w pułapkę myślenia, że ​​JavaScript delete jest odpowiedzią. Wydaje się, że jest przez wielu sugerowany, ale nie wykona tej pracy. Here to świetne odniesienie do zrozumienia usunąć przez Kangax.

+1

, może możesz pokazać jsFiddle, aby to potwierdzić. Dzięki – Muhaimin

+1

Potwierdzam to zachowanie. Moja struktura korzysta z drzewa mapowania obiektów JavaScript w układzie domowym. Każdy obiekt js odwołuje się do swojego elementu dom. Mimo że nazywam 'element.parentNode.removeChild', aby usunąć elementy, pozostają one żywe i nadal można się do nich odwoływać. Po prostu nie są widoczne w zwykłym drzewie domowym. – Sebas

+0

Tak, a następnie usunięcie globalnego wskaźnika do tego obiektu odwzorowania js magicznie odblokowuje garbage collector. Jest to ważny dodatek do zaakceptowanej odpowiedzi. – Sebas

39

W większości przeglądarek istnieje nieco bardziej zwięzły sposób na usunięcie elementu z DOM niż wywołanie .removeChild(element) na jego rodzica, który ma po prostu zadzwonić pod numer element.remove(). W odpowiednim czasie stanie się to prawdopodobnie standardowym i idiomatycznym sposobem usuwania elementu z DOM.

Metoda .remove() została dodana do DOM Living Standard w 2011 roku (commit) i została zaimplementowana w przeglądarce Chrome, Firefox, Safari, Opera i Edge. Nie było obsługiwane w żadnej wersji Internet Explorera.

Jeśli chcesz obsługiwać starsze przeglądarki, musisz je przesłać. Okazuje się, że jest to trochę irytujące, ponieważ nikt nie wydaje się mieć uniwersalnego podkładu DOM, który zawiera te metody, i ponieważ nie tylko dodajemy metodę do pojedynczego prototypu; jest to metoda ChildNode, która jest tylko interfejsem zdefiniowanym przez specyfikację i nie jest dostępna dla JavaScript, więc nie możemy dodać niczego do jej prototypu. Musimy więc znaleźć wszystkie prototypy dziedziczące po ChildNode i faktycznie zdefiniowane w przeglądarce, i dodać do nich .remove.

Oto podkładka, którą wymyśliłem, co potwierdziłem w 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; 
     } 
    } 
})(); 

To nie zadziała w IE 7 lub niższej wersji od extending DOM prototypes isn't possible before IE 8. Sądzę jednak, że na przełomie 2015 r. Większość ludzi nie potrzebuje takich rzeczy.

Po zawarte je podkładkę, będziesz w stanie usunąć element DOM element od DOM po prostu dzwoniąc

element.remove(); 
+1

Zostawiając to tutaj: https://polyfill.io/v2/docs/features/#Element_prototype_remove, jeśli dodasz tę automagiczną usługę polyfill, otrzymasz wsparcie z powrotem do IE 7. – complistic

+2

To zdecydowanie jest sposób na zrobienie tego w 2017 roku jako tak długo, jak nie zależy ci na IE. Zobacz: https://developer.mozilla.org/en-US/docs/Web/API/ChildNode/remove – nevf

1

Korzystanie Node.removeChild() nie praca dla ciebie, po prostu użyć czegoś takiego:

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

w Domu 4, zastosowana metoda usuwania, ale jest słaba obsługa przeglądarki według W3C:

Metoda node.remove() jest zaimplementowana w specyfikacji DOM 4. Ale z powodu słabej obsługi przeglądarki, nie powinieneś z niego korzystać.

Ale można użyć metody usunąć, jeśli używasz jQuery ...

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

Również w nowych ram jak można wykorzystać warunki, aby usunąć element, na przykład *ngIf w kątowe i React, rendering różne widoki, zależą od warunków ...