2012-01-12 6 views
136

Я пытаюсь проверить, существует ли элемент DOM, и если он существует, удалите его, а если он не существует, создайте его.JavaScript DOM remove 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); 
} 

Проверка наличия работы, создание элемента работает, но удаление элемента не происходит. В принципе, весь этот код вводит iframe в веб-страницу, нажав кнопку. Я бы хотел, чтобы iframe уже там, чтобы удалить его. Но по какой-то причине я терплю неудачу.

+0

Возможный дубликат [JavaScript: удалить элемент по id] (http://stackoverflow.com/questions/3387427/javascript-remove-element-by-id) – Zaz

ответ

253

removeChild следует ссылаться на родителя, то есть:

parent.removeChild(child); 

В вашем примере, вы должны делать что-то вроде:

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

Спасибо, что понял это прямо перед тем, как я прочитаю ваш пост. Пришлось изменить его на whereto.removeChild (whereto.childNodes [0]); –

+6

Это также будет работать, если предположить, что ваш кадр всегда является первым дочерним элементом 'debug' div. Использование 'parentNode' - более общее решение, которое будет работать с любым элементом. – casablanca

+1

Этого решения может быть недостаточно. Если кто-то читает это, пожалуйста, взгляните на предложение Гленна – Sebas

37

Кажется, у меня нет достаточного количества респ чтобы добавить комментарий, так что еще один ответ должен будет сделать.

Когда вы отсоединяете узел с помощью removeChild() или устанавливаете свойство innerHTML на родительском объекте, вам также необходимо убедиться, что нет ничего другого, ссылающегося на него, иначе он фактически не будет уничтожен и приведет к памяти протечь. Существует множество способов, с помощью которых вы могли бы получить ссылку на узел перед вызовом removeChild(), и вы должны убедиться, что ссылки, которые не вышли из области действия, явно удалены.

Doug Крокфорд пишет 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.

+1

, возможно, вы можете показать некоторые jsFiddle, чтобы это доказать. Спасибо – Muhaimin

+1

Я подтверждаю это поведение. Моя структура использует дерево сопоставления объектов Javascript над макетом dom. Каждый объект js ссылается на свой элемент dom. Несмотря на то, что я вызываю 'element.parentNode.removeChild' для удаления элементов, они остаются в живых и по-прежнему могут ссылаться на них. Они просто не видны в обычном дереве. – Sebas

+0

Да, а затем удаление глобального указателя на этот объект сопоставления js волшебным образом разблокирует сборщик мусора. Это важное дополнение к принятому ответу. – Sebas

39

В большинстве браузеров есть несколько более краткий способ удаления элемента из DOM, чем вызов .removeChild(element) на его родительский элемент, который должен просто вызвать element.remove(). Со временем это, вероятно, станет стандартным и идиоматическим способом удаления элемента из DOM.

Метод .remove() был добавлен в DOM Living Standard в 2011 году (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 элемент element из DOM, просто вызывая

element.remove(); 
+1

Просто оставив это здесь: https://polyfill.io/v2/docs/features/#Element_prototype_remove, если вы включите этот автозаправочный сервис, вы получите поддержку в IE 7. – complistic

+2

Это определенно способ сделать это в 2017 году как если вам неинтересно IE. См. Https://developer.mozilla.org/en-US/docs/Web/API/ChildNode/remove – nevf

1

Использование Node.removeChild() делает работу для вас, просто использовать что-то вроде этого:

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

в DOM 4, метод удалить применяется, но есть слабая поддержка браузера в соответствии с W3C:

Метод node.remove() реализован в спецификации DOM 4. Но из-за плохой поддержки браузера вы не должны его использовать.

Но вы можете использовать метод удалить, если вы используете JQuery ...

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

Кроме того, в новых рамках, как вы можете использовать условие, чтобы удалить элемент, например *ngIf в угловом и в React, оказание разные взгляды, зависит от условий ...