Usuń element według identyfikatora

1128

Podczas usuwania elementu ze standardowym JavaScript należy najpierw przejść do jego elementu nadrzędnego:

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

Konieczność przejścia do węzła nadrzędnego wydaje mi się nieco dziwna, czy istnieje powód, dla którego JavaScript działa w ten sposób?

Zaz
źródło
534
Jak powiedział James, DOM nie obsługuje bezpośredniego usuwania obiektu. Musisz iść do jego rodzica i usunąć go stamtąd. JavaScript nie pozwala elementowi popełnić samobójstwa, ale dopuszcza się dzieciobójstwa ...
Mark Henderson
21
Czy jest powód? Richard Feynman mówi nie . (No cóż, techniczne uzasadnienie jest łatwe do stwierdzenia, czy napisałeś jakieś programy do struktury drzew. Dziecko musi i tak poinformować rodzica, w przeciwnym razie struktura drzewa może zostać uszkodzona. Ponieważ i tak musi to zrobić wewnętrznie, jeśli zapewniło ci funkcję jednowierszową , jest to dla Ciebie tylko wygodna funkcja, którą możesz równie dobrze zdefiniować.)
kizzx2
6
Jedyny powód, dla którego widzę to to, że zawsze powinien być element główny w dokumencie xml / xhtml, więc nie będzie można go usunąć, ponieważ nie ma on elementu nadrzędnego
Alex K
5
Bardzo podoba mi się obejście Johana i nie jestem pewien, dlaczego te funkcje nie są dostarczane natywnie. Jak pokazuje liczba widzów, jest to bardzo częsta operacja.
Zaz
12
Możesz używać element.remove()bezpośrednio od ES5. Nie potrzebujesz rodzica!
Gibolt,

Odpowiedzi:

659

Wiem, że rozszerzanie natywnych funkcji DOM nie zawsze jest najlepszym lub najpopularniejszym rozwiązaniem, ale działa dobrze w nowoczesnych przeglądarkach.

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

Następnie możesz usunąć takie elementy

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

lub

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

Uwaga: to rozwiązanie nie działa dla IE 7 i niższych. Aby uzyskać więcej informacji o rozszerzaniu DOM, przeczytaj ten artykuł .

EDYCJA : Przeglądając moją odpowiedź w 2019 r. node.remove()Przyszedł mi na ratunek i może być używany w następujący sposób (bez powyższego wypełnienia):

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

lub

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

Te funkcje są dostępne we wszystkich nowoczesnych przeglądarkach (nie IE). Czytaj więcej na MDN .

Johan Dettmar
źródło
3
Nie powinno to być [document.getElementsByClassName („my-elements”) [0] .remove (); ] Myślę, że funkcja remove () nie jest zaimplementowana przez tablice. Aby usunąć wszystkie elementy klasy lub dowolny selektor zwracający tablicę, musisz iterować po wszystkich elementach i wywołać metodę remove () na każdym z nich.
Sedat Kilinc
1
@SedatKilinc, czy wypróbowałeś już fragment kodu? Nie są zaangażowane żadne tablice, ale raczej NodeListlub HTMLCollectionktóre są zestawem elementów podobnych do tablicy. Druga definicja metody pozwala na usunięcie tych „zestawów elementów”.
Johan Dettmar
1
Uruchamianie tego w konsoli chrome wydaje się usuwać tylko jeden element na raz podczas używania document.getElementsByClassName("my-elements").remove();. Edycja: faktycznie usuwa kilka, ale wymaga ponownego uruchomienia, aby zakończyć. Wypróbuj na tej stronie z klasą „kopiuj komentarze”.
DanielST
2
@slicedtoad masz rację, mój zły. Zmodyfikowałem tę funkcję, aby pętla przechodziła wstecz przez elementy. Wydaje się, że działa dobrze. Zachowanie, o którym mówisz, jest najprawdopodobniej spowodowane przez zaktualizowane indeksy.
Johan Dettmar
1
Nie rób tego Po prostu usuwaj elementy zgodnie z intencjami języka. Każdy, kto zna się na analizowaniu XML, rozpozna potrzebę skontaktowania się z rodzicem w celu usunięcia dzieci. HTML jest nadzbiorem XML (swego rodzaju).
Hal50000
283

Crossbrowser i IE> = 11:

document.getElementById("element-id").outerHTML = "";
użytkownik2192293
źródło
3
To wydaje się najprostsze, najbardziej niezawodne i najszybsze rozwiązanie. Nie muszę usuwać elementu, więc pomijam ostatni wiersz, ale to nie powinno dodawać żadnego obciążenia w żaden sposób. Uwaga : Znalazłem to, próbując znaleźć szybszą niż $.readyjs alternatywę dla noscripttagów. Aby użyć go tak, jak chciałem, musiałem zawinąć go w funkcję 1ms setTimeout. To rozwiązuje wszystkie moje problemy naraz. Gracias.
dgo
Pamiętaj, że outerHTMLwciąż jest nowym (er) dodatkiem do standardu. Jeśli szukasz wsparcia dla dowolnego oprogramowania> 6 w momencie pisania, potrzebujesz innego rozwiązania. removeFunkcja wspomniano przez innych jest podobna sprawa. Jak zwykle bezpieczne jest stosowanie wypełniacza.
Super Cat,
delete elementnic nie robi, bo nie można usunąć zmiennych w JS, tylko klucze;) Sprawdź sam, czy nie działa console.log(element)po delete element...
Ivan Kleshnin
2
Jest to nieco wolniejsze niż removeChild(około 6-7% w moim systemie). Zobacz jsperf.com/clear-outerhtml-v-removechild/2
Alejandro García Iglesias
1
Może to pozostawić miejsce, w którym kiedyś znajdował się element iframe, jeśli właśnie to próbujesz usunąć.
lacostenycoder
164

Możesz stworzyć removefunkcję, abyś nie musiał za każdym razem o niej myśleć:

function removeElement(id) {
    var elem = document.getElementById(id);
    return elem.parentNode.removeChild(elem);
}
xsznix
źródło
12
Jeśli chcesz mieć liniowiec bez globalizacji, możesz zmienić elemna remove.elem. W ten sposób funkcja odwołuje się do siebie, więc nie musisz tworzyć innej zmiennej globalnej. :-)
twiz
4
więc dlaczego musisz zwrócić element? Dlaczego niefunction remove(id) { document.getElementById(id).parentNote.removeChild(document.getElementById(id)); }
Zach Lysobey,
4
@ZachL: Chociaż twoje rozwiązanie może wydawać się bardziej oczywiste, wykonuje dwa wyszukiwania DOM, które są wolniejsze i coś, czego inne rozwiązania wydają się unikać.
Wk_of_Angmar
3
Nie działa. Za dużo błędów. Działa to: var elem = document.getElementById ('id'); elem.parentNode.removeChild (elem);
Mitch Match
2
Wow, dlaczego tak skomplikowane. Wystarczy przekazać sam element do funkcji zamiast ciągu id. W ten sposób element jest dostępny w całej funkcji i pozostaje w jednym wierszu
David Fariña,
97

To właśnie obsługuje DOM . Wyszukaj na tej stronie „usuń” lub „usuń”, a removeChild jest jedyną, która usuwa węzeł.

Christian Sirolli
źródło
13
To odpowiada na moje pierwotne pytanie, ale dlaczego JavaScript działa w ten sposób?
Zaz
5
Zgaduję tutaj, ale zakładam, że ma to związek z zarządzaniem pamięcią. Węzeł nadrzędny najprawdopodobniej zawiera listę wskaźników do węzłów podrzędnych. Jeśli właśnie usunąłeś węzeł (bez użycia rodzica), rodzic nadal trzymałby wskaźnik i spowodowałby przeciek pamięci. Interfejs API zmusza cię do wywołania funkcji nadrzędnej w celu usunięcia dziecka. jest to również miłe, ponieważ może poprowadzić drzewo przez węzły potomne, wywołując usunięcie na każdym z nich i nie przeciekając pamięci.
Chadams
2
cześć chłopaki, mimo że ten odnośnik tego nie ma, znalazłem to przypadkowo. pisanie element.remove();zadziała. Może to coś nowego. Ale pierwszy raz dla mnie i to działa. Myślę, że to powinno zawsze działać, ponieważ to bardzo podstawowe musi mieć rzeczy.
Muhammad Umer
1
Ale to nie działa w IE7 i niższych. Z IE7 i niższych, remove () nie działa
fanfan1609
1
Gdybym musiał zgadywać, powodem takiego działania jest to, że elementy DOM nie mogą się same usunąć. Usuwasz przysłowiowy dywan spod jego stóp. Musisz go usunąć z pojemnika. Przynajmniej tak o tym myślę.
PhilT
82

DOM jest zorganizowany w drzewie węzłów, gdzie każdy węzeł ma wartość, wraz z listą odniesień do jego węzłów potomnych. element.parentNode.removeChild(element)Naśladuje więc dokładnie to, co dzieje się wewnętrznie: Najpierw przejdź do węzła nadrzędnego, a następnie usuń odwołanie do węzła podrzędnego.

Począwszy od DOM4, funkcja pomocnika jest zrobić to samo: element.remove(). To działa w 87% przeglądarek (stan na rok 2016), ale nie IE 11. Jeśli trzeba wspierać starszych przeglądarek, możesz:

Zaz
źródło
2
Proszę nie „modyfikować natywnych funkcji DOM” .
Emile Bergeron,
36

Aby usunąć jeden element:

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

Aby usunąć wszystkie elementy, na przykład o określonej nazwie klasy:

 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]);
csjpeter
źródło
Jest to dobrze uwzględnione w istniejących odpowiedziach.
KyleMit,
4
+1 Prosty przykład usuwania według nazwy klasy. To nie jest dobrze uwzględnione w innych odpowiedziach
Louise Eggleton
Dlaczego if(list[i] && list[i].parentElement)linia jest konieczna? Czy istnienie każdego elementu nie jest gwarantowane przez fakt, że został zwrócony getElementsByClassNamemetodą?
Hydrotermalny
Niestety, o ile wiem, istnienie nie jest tak naprawdę gwarantowane, ale nie znam szczegółów na jego temat. Po raz pierwszy doświadczyłem dziwnej niezdefiniowanej lub zerowej wartości i sprawdziłem to bez dalszego badania. To trochę hack.
csjpeter
Powinno byćdocument.getElementsByClassName(...
Worker
21

możesz po prostu użyć element.remove()

Sai Sunder
źródło
13
element.remove()nie jest prawidłowym skryptem JavaScript i działa tylko w niektórych przeglądarkach, takich jak Chrome .
Zaz
4
Josh, to jest poprawny javascript, z wyjątkiem tego, że tylko Firefox i Chrome go zaimplementowały (patrz MDN)
Tim Nguyen,
10
Moją wadą element.remove() jest poprawny JavaScript w DOM4 i działa we wszystkich nowoczesnych przeglądarkach, oczywiście z wyjątkiem Internet Explorera.
Zaz
24
Działa dobrze w FireFox i Chrome. kogo to obchodzi o IE
Arun Sharma
13
osoby pracujące dbają o IE!
sqram
18

ChildNode.remove()Metoda usuwa obiekt z drzewa, do której należy.

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

Oto skrzypce, które pokazują, jak możesz zadzwonić document.getElementById('my-id').remove()

https://jsfiddle.net/52kp584L/

**

Nie ma potrzeby rozszerzania NodeList. Zostało już wdrożone.

**

Alex Fallenstedt
źródło
2
Uwaga, nie jest to obsługiwane w żadnej wersji IE!
MacroMan
1
Jeśli nadal pracujesz nad IE, jest mi bardzo przykro.
Alex Fallenstedt
Nie rozwijasz się dla IE? Bardzo mi przykro z powodu waszych klientów.
MacroMan
13

Możesz bezpośrednio usunąć ten element za pomocą remove()metody DOM.

oto przykład:

let subsWrapper = document.getElementById("element_id");
subsWrapper.remove();
//OR directly.
document.getElementById("element_id").remove();
Code Cooker
źródło
7

Konieczność przejścia do węzła nadrzędnego wydaje mi się nieco dziwna, czy istnieje powód, dla którego JavaScript działa w ten sposób?

Nazwa funkcji to removeChild()i jak można usunąć dziecko, gdy nie ma rodzica? :)

Z drugiej strony nie zawsze trzeba nazywać to tak, jak pokazano. element.parentNodejest tylko pomocnikiem, aby uzyskać węzeł nadrzędny danego węzła. Jeśli znasz już węzeł nadrzędny, możesz go po prostu użyć w następujący sposób:

Dawny:

// 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

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

Aby dodać coś więcej:

Niektóre odpowiedzi wskazują, że zamiast używać parentNode.removeChild(child);, możesz użyć elem.remove();. Ale, jak zauważyłem, istnieje różnica między tymi dwiema funkcjami i nie jest o nich mowa w tych odpowiedziach.

Jeśli użyjesz removeChild(), zwróci odwołanie do usuniętego węzła.

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

Ale jeśli użyjesz elem.remove();, nie zwróci ci referencji.

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

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

Takie zachowanie można zaobserwować w Chrome i FF. Myślę, że warto to zauważyć :)

Mam nadzieję, że moja odpowiedź dodaje pewnej wartości do pytania i będzie pomocna !!

Nimeshka Srimal
źródło
6

Funkcje korzystające z ele.parentNode.removeChild (ele) nie będą działać w przypadku elementów utworzonych, ale jeszcze nie wstawionych do kodu HTML. Biblioteki takie jak jQuery i Prototype mądrze używają metody podobnej do poniższej, aby ominąć to ograniczenie.

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

Myślę, że JavaScript działa w ten sposób, ponieważ oryginalni projektanci DOM utrzymywali nawigację nadrzędną / podrzędną oraz poprzednią / następną nawigację jako wyższy priorytet niż tak popularne dziś modyfikacje DHTML. Możliwość czytania z jednego <input type = 'text'> i pisania do drugiego według względnej lokalizacji w DOM była przydatna w połowie lat 90., kiedy dynamiczne generowanie całych formularzy HTML lub interaktywnych elementów GUI było zaledwie migotaniem oko jakiegoś dewelopera.

Psudo
źródło
3

Konieczność przejścia do węzła nadrzędnego wydaje mi się nieco dziwna, czy istnieje powód, dla którego JavaScript działa w ten sposób?

IMHO: Powód tego jest taki sam, jak widziałem w innych środowiskach: wykonujesz akcję na podstawie swojego „linku” do czegoś. Nie możesz go usunąć, gdy jesteś z nim połączony.

Jak ścinanie gałęzi drzewa. Podczas cięcia usiądź na boku najbliżej drzewa, w przeciwnym razie wynik będzie ... niefortunny (choć zabawny).

TheSatinKnight
źródło
2

Ten faktycznie pochodzi z FireFox ... tym razem IE wyprzedził paczkę i pozwolił na usunięcie elementu bezpośrednio.

To tylko moje założenie, ale uważam, że powodem, dla którego musisz usunąć dziecko za pośrednictwem rodzica, jest problem ze sposobem, w jaki FireFox obsługiwał referencję.

Jeśli wywołujesz obiekt, aby bezpośrednio popełnić hari-kari, to zaraz po jego śmierci nadal masz do niego odniesienie. Może to spowodować kilka paskudnych błędów ... takich jak nieusunięcie go, usunięcie go, ale zachowanie referencji, które wydają się prawidłowe, lub po prostu wyciek pamięci.

Wierzę, że kiedy zdali sobie sprawę z tego problemu, obejście polegało na usunięciu elementu przez jego element nadrzędny, ponieważ gdy element zniknie, teraz po prostu trzymasz odniesienie do elementu nadrzędnego. To powstrzymałoby całą tę nieprzyjemność i (na przykład, zamykając węzeł drzewa po węźle) całkiem ładnie się „spakowało”.

Powinien to być łatwy do naprawienia błąd, ale podobnie jak w przypadku wielu innych rzeczy w programowaniu internetowym, wydanie prawdopodobnie zostało przyspieszone, co doprowadziło do tego ... a zanim pojawiła się kolejna wersja, wystarczająca liczba osób korzystała z niego, że zmiana tego doprowadziłaby do złamania kawałka kodu.

Znowu wszystko to jest po prostu zgadywaniem.

Z niecierpliwością czekam jednak na dzień, w którym programowanie sieciowe zostanie w końcu całkowicie wyczyszczone na wiosnę, wszystkie te dziwne małe dziwactwa zostaną oczyszczone i wszyscy zaczną grać na tych samych zasadach.

Prawdopodobnie dzień po tym, jak mój robot-robot pozwał mnie o zaległe płace.

SilentThunderStorm
źródło
10
Wątpię, aby Firefox był za to odpowiedzialny. removeChildjest metodą interfejsu DOM Level 1Node .
Felix Kling
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);
}
będzie Farrell
źródło
-3

To najlepsza funkcja do usuwania elementu bez błędu skryptu:

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

Uwaga do EObj=document.getElementById(EId).

To JEDEN znak równości nie ==.

jeśli element EIdistnieje, funkcja go usuwa, w przeciwnym razie zwraca false, a nie error.

Amin Atabakzadeh
źródło
4
Tworzy zmienną globalną.
bjb568
1
To także najgorsza wersja innej odpowiedzi , ale spóźniona o 2 lata.
Emile Bergeron,