Удалить элемент JavaScript DOM

Я пытаюсь проверить, существует ли элемент 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 content into the DOM
    my_div = document.getElementById("debug");
    document.body.insertBefore(iframe, my_div);
}

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

Ответ 1

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

parent.removeChild(child);

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

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

Ответ 2

В большинстве браузеров есть несколько более краткий способ удаления элемента из 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 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 root node, so let 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 или ниже, поскольку расширение прототипов DOM невозможно до IE 8. Я полагаю, однако, что на пороге 2015 года большинству людей не нужно заботиться о таких вещах.

Как только вы включите их, вы сможете удалить элемент DOM element из DOM, просто позвонив

element.remove();

Ответ 3

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

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

Doug Crockford пишет здесь, что обработчики событий известны как причина циклических ссылок в 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 здесь.

И, наконец, не попадайте в ловушку, думая, что Javascript удалить - это ответ. По-видимому, многие предлагают, но не будут выполнять эту работу. Здесь - отличная ссылка на понимание удаления Kangax.

Ответ 4

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

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

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

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

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

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

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