Видаліть елемент за ідентифікатором


1129

Видаляючи елемент зі стандартним JavaScript, потрібно спочатку перейти до його батьківського:

var element = document.getElementById("element-id");
element.parentNode.removeChild(element);

Перехід до батьківського вузла спочатку здається мені трохи дивним, чи є причина JavaScript, як це працює?


534
Як сказав Джеймс, DOM не підтримує видалення об'єкта безпосередньо. Ви повинні зайти до його батьківського і вийняти його звідти. Javascript не дозволить стихії покінчити життя самогубством, але це дозволяє дозволити дітям ...
Марк Хендерсон

21
Чи є причина? Річард Фейнман каже, що ні . (Ну технічне обгрунтування легко побачити , якщо ви написали якусь - яку програму деревовидної структури. Дитина повинна інформувати батько в будь-якому випадку , інакше структура дерева може бути порушена. Так як він повинен робити це внутрішньо в будь-якому випадку, якщо це передбачено вам функцію одна лінії , це просто зручна для вас функція, яку ви також можете самі визначити.)
kizzx2

6
Єдиною причиною, яку я бачу, є те, що в документі xml / xhtml завжди повинен бути кореневий елемент, тому ви не зможете його видалити, оскільки у нього немає батьків
Alex K

5
Мені дуже подобається вирішення Йогана , і я не впевнений, чому ці функції не надаються в основному. Як свідчить кількість глядачів, це дуже поширена операція.
Заз

12
Ви можете використовувати element.remove()безпосередньо з ES5. Вам не потрібен батько!
Гібольт

Відповіді:


659

Я знаю, що розширення функцій рідного DOM не завжди є найкращим чи найпопулярнішим рішенням, але це добре працює для сучасних браузерів.

Element.prototype.remove = function() {
    this.parentElement.removeChild(this);
}
NodeList.prototype.remove = HTMLCollection.prototype.remove = function() {
    for(var i = this.length - 1; i >= 0; i--) {
        if(this[i] && this[i].parentElement) {
            this[i].parentElement.removeChild(this[i]);
        }
    }
}

І тоді ви можете видалити подібні елементи

document.getElementById("my-element").remove();

або

document.getElementsByClassName("my-elements").remove();

Примітка. Це рішення не працює для IE 7 та нижче. Для отримання додаткової інформації про розширення DOM читайте цю статтю .

EDIT : Переглядаючи мою відповідь у 2019 році, node.remove()допомогла допомогти і її можна використовувати наступним чином (без поліетилену вище):

document.getElementById("my-element").remove();

або

[...document.getElementsByClassName("my-elements")].map(n => n && n.remove());

Ці функції доступні у всіх сучасних браузерах (не в IE). Детальніше читайте на MDN .


3
Чи не повинно бути це [document.getElementsByClassName ("мої елементи") [0] .remove (); ] Я думаю, що функція delete () ist не реалізована масивами. Для того, щоб видалити всі елементи класу або будь-якого селектора, що повертає масив, вам слід повторити всі елементи та викликати delete () на кожному.
Седат Кілінк

1
@SedatKilinc, ви спробували фактичний фрагмент? Там немає масивів , що беруть участь, а скоріше , NodeListабо HTMLCollectionякі є масивом як набір елементів. Визначення другого методу дозволяє видалити ці "набори елементів".
Йохан Деттмар

1
Запустивши це в хромованій консолі, здається, видаляється одночасно один елемент при використанні document.getElementsByClassName("my-elements").remove();. Правка: насправді вона видаляє купу, але для її завершення потрібен повторний запуск. Спробуйте це на цій сторінці з класом "коментар-копія".
ДаніельST

2
@slicedtoad ти маєш рацію, моя погана. Я змінив функцію, щоб цикліти назад через елементи. Здається, добре працює. Поведінка, про яку ви говорите, швидше за все, викликана оновленими індексами.
Йохан Деттмар

1
Не робіть цього. Просто видаліть предмети так, як мова призначена. Усі, знайомі з розбором XML, визнають необхідність потрапити до батьків, щоб видалити дітей. HTML - це набір XML (свого роду).
Hal50000

283

Кроссбоузер і IE> = 11:

document.getElementById("element-id").outerHTML = "";

3
Це здається найпростішим, найнадійнішим та найшвидшим рішенням. Мені не потрібно видаляти елемент, тому я пропускаю останній рядок, але це не повинно додавати накладних витрат. Примітка . Я знайшов це, намагаючись знайти швидшу, ніж $.readyjs альтернативу noscriptтегам. Для того, щоб використовувати його так, як я хотів, мені довелося загорнути його у функцію 1 мс setTimeout. Це вирішує всі мої проблеми одразу. Грацій.
dgo

Майте на увазі, outerHTMLце все-таки нове доповнення до стандарту. Якщо ви шукаєте підтримки для будь-якого програмного забезпечення> 6 на момент написання, вам знадобиться інше рішення. removeФункція вже відзначалися іншими є подібним випадком. Як завжди, безпечно реалізувати поліфіл.
Супер Кіт

delete elementне робить нічого, оскільки ви не можете видалити змінні в JS, лише клавіші;) Перевірте, чи не працює вона console.log(element)після delete element...
Іван Клешнін

2
Це трохи повільніше, ніж removeChild(приблизно 6-7% у моїй системі). Дивіться jsperf.com/clear-outerhtml-v-removechild/2
Алехандро Гарсія Іглесіас

1
Це може залишити місце, де раніше був кадр iframe, якщо саме це ви намагаєтесь видалити.
lacostenycoder

164

Ви можете зробити removeфункцію так, що вам не доведеться думати про неї кожен раз:

function removeElement(id) {
    var elem = document.getElementById(id);
    return elem.parentNode.removeChild(elem);
}

12
Якщо ви хочете, щоб однолінійка не переходила на глобальний рівень, можете перейти elemна remove.elem. Таким чином функція посилається на себе, тому вам не доведеться створювати ще одну глобальну змінну. :-)
twiz

4
Отже, навіщо вам повертати елем? Чому б і ніfunction remove(id) { document.getElementById(id).parentNote.removeChild(document.getElementById(id)); }
Зах Лісобей

4
@ZachL: Хоча ваше рішення може здатися більш очевидним, воно виконує два пошуку DOM, які повільніше, і чого, схоже, хочуть уникнути інші рішення.
Wk_of_Angmar

3
Не працює. Занадто багато помилок. Це працює: var elem = document.getElementById ('id'); elem.parentNode.removeChild (elem);
Матч Мітч

2
Нічого собі, чому так складно. Просто передайте сам елемент функції замість рядка id. Таким чином елемент доступний у всій функції, а також залишається одним вкладишем
Девід Фарінья,

97

Це те, що підтримує DOM . Шукайте на цій сторінці "видалити" або "видалити" і видалитиChild - це єдиний, який видаляє вузол.


13
Це відповідає на моє оригінальне запитання, але чому JavaScript працює так?
Заз

5
Я просто здогадуюсь тут, але я вважаю, що це стосується управління пам'яттю. Батьківський вузол, швидше за все, містить список покажчиків на дочірні вузли. Якщо ви тільки що видалили вузол (не використовуючи батьківський), він все одно буде утримувати покажчик і спричинити витік пам'яті. Таким чином, api змушує вас викликати функцію на батьків для видалення дитини. це також приємно, оскільки воно може ходити по дереву через дочірні вузли, закликаючи видалити кожен з них, і не протікати пам'ять.
Чадам

2
Ей, хлопці, хоча ця посилання не має цього, я знайшов це випадково. написання element.remove();буде працювати. Можливо, це щось нове. Але перший раз для мене це і працює. Я думаю, що це повинно діяти завжди, оскільки це дуже базові речі.
Мухаммед Умер

1
Але це не працює в IE7 та нижче. З IE7 і нижче, видалити () не працює
fanfan1609

1
Якби мені довелося здогадатися, причина цього працює так, це те, що елементи DOM не можуть видалити себе. Ви виймаєте з-під ніг пословичний килим. Ви повинні вийняти його з контейнера. Принаймні так я намагаюся це думати.
PhilT

82

DOM організований у дереві вузлів, де кожен вузол має значення разом зі списком посилань на його дочірні вузли. Тож element.parentNode.removeChild(element)імітує саме те, що відбувається всередині: Спочатку ви переходите на батьківський вузол, а потім видаляєте посилання на дочірній вузол.

За DOM4, функція помічника надається робити те ж саме: element.remove(). Це працює у 87% браузерів (станом на 2016 рік), але не IE 11. Якщо вам потрібно підтримувати старіші браузери, ви можете:


2
Будь ласка, не "змінюйте нативні функції DOM" .
Еміль Бержерон

36

Для видалення одного елемента:

 var elem = document.getElementById("yourid");
 elem.parentElement.removeChild(elem);

Для видалення всіх елементів, наприклад, певного імені класу:

 var list = document.getElementsByClassName("yourclassname");
 for(var i = list.length - 1; 0 <= i; i--)
 if(list[i] && list[i].parentElement)
 list[i].parentElement.removeChild(list[i]);

Це добре висвітлено в існуючих відповідях.
KyleMit

4
+1 Простий приклад видалення за назвою класу. Це не добре висвітлено іншими відповідями
Луїза Еглтон

Для чого if(list[i] && list[i].parentElement)потрібна лінія? Чи не гарантоване існування кожного елемента тим, що він був повернутий getElementsByClassNameметодом?
Гідротермальний

На жаль, існування насправді не гарантоване, наскільки я знаю, але я не знаю деталей про це. Я просто відчув якесь дивне невизначене або нульове значення один раз, і я поставив цю перевірку там без подальшого дослідження. Так що це трохи хак.
csjpeter

Це має бутиdocument.getElementsByClassName(...
Робітник

21

ви можете просто використовувати element.remove()


13
element.remove()Недійсний JavaScript і працює лише в певних браузерах, таких як Chrome .
Заз

4
Джош, це дійсний javascript, за винятком лише Firefox та Chrome, який реалізував його (Див. MDN)
Тім Нгуен

10
Моє погане, element.remove() є дійсним JavaScript з DOM4 , і працює у всіх сучасних браузерах, природно , за винятком Internet Explorer.
Заз

24
Відмінно працює на FireFox та Chrome. кого турбує IE
Arun Sharma

13
люди з роботою дбають про IE!
sqram

18

ChildNode.remove()Метод видаляє об'єкт з дерева , якому він належить.

https://developer.mozilla.org/en-US/docs/Web/API/ChildNode/remove

Ось загадка, яка показує, як можна телефонувати document.getElementById('my-id').remove()

https://jsfiddle.net/52kp584L/

**

Не потрібно розширювати NodeList. Це вже реалізовано.

**


2
Зауважте, це не підтримується в будь-якій версії IE!
MacroMan

1
Якщо ви все ще розвиваєтесь для IE, я вам дуже шкода.
Алекс Фалленштедт

Ви не розвиваєтесь для IE? Мені дуже шкода ваших клієнтів чи клієнтів.
MacroMan

13

Ви можете безпосередньо видалити цей елемент, використовуючи remove()метод DOM.

ось приклад:

let subsWrapper = document.getElementById("element_id");
subsWrapper.remove();
//OR directly.
document.getElementById("element_id").remove();


7

Перехід до батьківського вузла спочатку здається мені трохи дивним, чи є причина JavaScript, як це працює?

Назва функції - це removeChild(), і як можна видалити дитину, коли немає батьків? :)

З іншого боку, вам не завжди потрібно називати це так, як ви показали. element.parentNodeє лише помічником для отримання батьківського вузла даного вузла. Якщо ви вже знаєте батьківський вузол, ви можете просто використовувати його так:

Наприклад:

// Removing a specified element when knowing its parent node
var d = document.getElementById("top");
var d_nested = document.getElementById("nested");
var throwawayNode = d.removeChild(d_nested);

https://developer.mozilla.org/en-US/docs/Web/API/Node/removeChild

===================================================== =======

Щоб додати щось більше:

Деякі відповіді вказували на те, що замість використання parentNode.removeChild(child);можна використовувати elem.remove();. Але, як я помітив, є різниця між двома функціями, і це не згадується в цих відповідях.

Якщо ви використовуєте removeChild(), він поверне посилання на видалений вузол.

var removedChild = element.parentNode.removeChild(element); 
console.log(removedChild); //will print the removed child.

Але якщо ви використовуєте elem.remove();, він не поверне вам посилання.

var el = document.getElementById('Example');
var removedChild = el.remove(); //undefined

https://developer.mozilla.org/en-US/docs/Web/API/ChildNode/remove

Таку поведінку можна спостерігати в Chrome та FF. Я вважаю, що це варто помітити :)

Сподіваюся, моя відповідь додасть певного значення питанню і буде корисною !!


6

Функції, які використовують ele.parentNode.removeChild (ele), не працюватимуть для створених вами елементів, але ще не вставлених у HTML. Бібліотеки, такі як jQuery і Prototype, розумно використовують такий метод, як наступний, щоб уникнути цього обмеження.

_limbo = document.createElement('div');
function deleteElement(ele){
    _limbo.appendChild(ele);
    _limbo.removeChild(ele);
}

Я думаю, що JavaScript працює так, тому що оригінальні дизайнери DOM вважали головним пріоритетом батьків / дитина та попередню / наступну навігацію, ніж модифікації DHTML, які так популярні сьогодні. Вміти читати з одного <вхідного типу = 'текст'> та писати до іншого за відносним розташуванням у DOM було корисно в середині 90-х, час, коли динамічне генерування цілих HTML-форм чи інтерактивних елементів графічного інтерфейсу ледве блимало якийсь погляд розробника.


3

Перехід до батьківського вузла спочатку здається мені трохи дивним, чи є причина JavaScript, як це працює?

ІМХО: Причина цього та сама, що я бачив в інших середовищах: Ви виконуєте дію, засноване на вашому "посиланні" на щось. Ви не можете видалити його, коли ви пов’язані з ним.

Як зрізання кінцівки дерева. Сидіти на стороні, найближчій до дерева, під час різання або результат буде ... невдалим (хоча і смішним).


2

Це насправді походить від FireFox ... Один раз IE випереджав пакет і дозволяв видаляти елемент безпосередньо.

Це лише моє припущення, але я вважаю, що причина того, що ви повинні видалити дитину через батьків, пов’язана з проблемою з тим, як FireFox обробляв посилання.

Якщо ви викликаєте об'єкт, щоб скористатися харі-карі безпосередньо, то одразу після того, як він відмирає, ви все ще тримаєтесь цього посилання на нього. Це може створити кілька неприємних помилок ... таких, як не вдалося їх видалити, видалити, але зберегти посилання на нього, які видаються дійсними, або просто витоку пам'яті.

Я вважаю, що коли вони зрозуміли цю проблему, вирішити проблему було видалення елемента через його батьків, тому що, коли елемента вже немає, ви просто тримаєте посилання на батьків. Це призведе до припинення всієї неприємності, і (якщо, наприклад, закрити деревцевий вузол за вузлом), він би «застебнути» досить непогано.

Це має бути легко виправлена ​​помилка, але, як і багато інших речей у веб-програмуванні, випуск, ймовірно, поспішав, що призвело до цього ... і до появи нової версії, достатньо людей використовували її, що змінити це призведе до щоб зламати купу коду.

Знову ж таки, все це просто мої здогадки.

Однак я з нетерпінням чекаю дня, коли веб-програмування нарешті отримає повне весняне прибирання, всі ці дивні маленькі ідіосинхронії очищаються, і всі починають грати за тими ж правилами.

Напевно, наступного дня після того, як мій робот-службовець подав до суду на мене за заробітну плату.


10
Сумніваюся, що за це відповідає Firefox. removeChildє методом інтерфейсу DOM рівня 1Node .
Фелікс Клінг

0

Як я розумію, видалення вузла безпосередньо не працює у Firefox, лише в Internet Explorer. Отже, щоб підтримати Firefox, вам потрібно піднятися до батьків, щоб видалити його дочірнім.

Посилання: http://chiragrdarji.wordpress.com/2007/03/16/removedelete-element-from-page-using-javascript-working-in-firefoxieopera/


6
Це насправді не відповідає на моє запитання, і сторінка, на яку ви посилаєтесь, пропонує гірше рішення, ніж моя.
Заз

0
// http://javascript.crockford.com/memory/leak.html
// cleans dom element to prevent memory leaks
function domPurge(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) {
            domPurge(d.childNodes[i]);
       }
    }
}

function domRemove(id) {
    var elem = document.getElementById(id);
    domPurge(elem);
    return elem.parentNode.removeChild(elem);
}

-3

Це найкраща функція для видалення елемента без помилки сценарію:

function Remove(EId)
{
    return(EObj=document.getElementById(EId))?EObj.parentNode.removeChild(EObj):false;
}

Примітка до EObj=document.getElementById(EId).

Це ОДИН знак рівності ні ==.

якщо елемент EIdіснує, то функція його видаляє, інакше він поверне помилковий, а не error.


4
Створює глобальну змінну.
bjb568

1
Це також найгірша версія іншої відповіді , але на 2 роки пізніше.
Еміль Бержерон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.