2012-01-12 32 views
136

Estoy tratando de probar si existe un elemento DOM, y si existe elimínelo, y si no existe, créelo.elemento DOM DOM eliminar

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

Comprobando si existe funciona, crear el elemento funciona, pero borrar el elemento no funciona. Básicamente, todo lo que hace este código es inyectar un iframe en una página web haciendo clic en un botón. Lo que me gustaría que ocurra es si el iframe ya está allí para eliminarlo. Pero por alguna razón estoy fallando.

+0

posible duplicado de [JavaScript: eliminar elemento por id] (http://stackoverflow.com/questions/3387427/javascript-remove-element-by-id) – Zaz

Respuesta

253

removeChild debe ser invocado en la matriz, es decir:

parent.removeChild(child); 

En su ejemplo, usted debe hacer algo como:

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

Gracias figura salir justo antes de leer su publicación. Tuve que cambiarlo a whereto.removeChild (whereto.childNodes [0]); –

+6

Eso también funcionaría suponiendo que su marco siempre es el primer elemento secundario de la div 'debug'. Usar 'parentNode' es una solución más genérica que funcionará con cualquier elemento. – casablanca

+1

Esta solución puede no ser suficiente. Si alguien está leyendo esto, eche un vistazo a la sugerencia de Glenn, – Sebas

37

Parece que no tengo representante suficiente para publicar un comenten, entonces otra respuesta tendrá que hacer.

Al desvincular un nodo utilizando removeChild() o al establecer la propiedad innerHTML en el elemento principal, también debe asegurarse de que no haya nada más que lo referencia, de lo contrario no se destruirá y llevará a una memoria fuga. Hay muchas formas en que podría haber tomado una referencia al nodo antes de llamar a removeChild() y debe asegurarse de que las referencias que no hayan salido del alcance se eliminen explícitamente.

Doug Crockford escribe here que los manejadores de eventos son conocidos una causa de referencias circulares en IE y les sugiere la eliminación explícita de la siguiente antes de llamar 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]); 
     } 
    } 
} 

E incluso si se toma una gran cantidad de precauciones que puede todavía tiene pérdidas de memoria en IE como lo describe Jens-Ingo Farley here.

Y, por último, no caiga en la trampa de pensar que Javascript eliminar es la respuesta. Parece ser sugerido por muchos, pero no hará el trabajo. Here es una gran referencia para entender eliminar de Kangax.

+1

; quizás pueda mostrar jsFiddle para probar esto. Gracias – Muhaimin

+1

Confirmo este comportamiento. Mi framework utiliza un árbol de mapeo de objetos JavaScript sobre el diseño dom. Cada objeto js hace referencia a su elemento dom. Aunque llamo a 'element.parentNode.removeChild' para eliminar elementos, se mantienen activos y aún se pueden hacer referencia a ellos. Simplemente no son visibles en el árbol dom regular. – Sebas

+0

Sí, y luego al quitar el puntero global a ese objeto de mapeo js se desbloquea mágicamente el recolector de basura. Esta es una adición importante a la respuesta aceptada. – Sebas

39

En la mayoría de los navegadores, hay una forma un poco más sucinta de eliminar un elemento del DOM que llamar al .removeChild(element) en su principal, que es simplemente llamar al element.remove(). A su debido tiempo, esto probablemente se convierta en la forma estándar e idiomática de eliminar un elemento del DOM.

El método .remove() se agregó al DOM Living Standard en 2011 (commit), y desde entonces ha sido implementado por Chrome, Firefox, Safari, Opera y Edge. No fue compatible con ninguna versión de Internet Explorer.

Si desea admitir navegadores más antiguos, deberá ajustarlo. Esto resulta ser un poco irritante, tanto porque nadie parece haber hecho un ajuste de DOM de uso múltiple que contenga estos métodos, y porque no estamos simplemente agregando el método a un solo prototipo; es un método de ChildNode, que es solo una interfaz definida por la especificación y no es accesible para JavaScript, por lo que no podemos agregar nada a su prototipo. Así que tenemos que encontrar todos los prototipos que heredan de ChildNode y están realmente definidos en el navegador, y agregarles .remove.

Aquí está la cuña que se me ocurrió, que he confirmado que funciona en 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; 
     } 
    } 
})(); 

Esto no funcionará en IE 7 o menor, ya que extending DOM prototypes isn't possible before IE 8. Me imagino, sin embargo, que a fines de 2015 la mayoría de la gente no necesita preocuparse por tales cosas.

Una vez que los ha incluido cuña, usted será capaz de eliminar un elemento DOM element del DOM simplemente llamando

element.remove(); 
+1

Dejando esto aquí: https://polyfill.io/v2/docs/features/#Element_prototype_remove si incluye ese servicio automático de polyfill obtendrá soporte de IE 7. – complistic

+2

Esta es definitivamente la manera de hacerlo en 2017 como siempre y cuando no te importe IE. Ver: https://developer.mozilla.org/en-US/docs/Web/API/ChildNode/remove – nevf

1

Usando Node.removeChild() hace el trabajo para usted, sólo tiene que utilizar algo como esto:

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

En DOM 4, el método remove aplica, pero no es un pobre soporte de los navegadores de acuerdo con W3C:

El método node.remove() se implementa en la especificación DOM 4. Pero debido a la compatibilidad deficiente del navegador, no debe usarlo.

Pero se puede utilizar el método de eliminación si el uso de jQuery ...

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

También en los nuevos marcos que se pueden utilizar como condiciones para eliminar un elemento, por ejemplo en *ngIf angular y en reaccionar, renderizado diferentes vistas, depende de las condiciones ...

Cuestiones relacionadas