Jak mogę sprawdzić, czy element istnieje w widocznym DOM?

421

Jak testujesz element pod kątem istnienia bez użycia getElementByIdmetody?

Przygotowałem demo na żywo w celach informacyjnych. Tutaj również wydrukuję kod:

<!DOCTYPE html>
<html>
<head>
    <script>
    var getRandomID = function (size) {
            var str = "",
                i = 0,
                chars = "0123456789abcdefghijklmnopqurstuvwxyzABCDEFGHIJKLMNOPQURSTUVWXYZ";
            while (i < size) {
                str += chars.substr(Math.floor(Math.random() * 62), 1);
                i++;
            }
            return str;
        },
        isNull = function (element) {
            var randomID = getRandomID(12),
                savedID = (element.id)? element.id : null;
            element.id = randomID;
            var foundElm = document.getElementById(randomID);
            element.removeAttribute('id');
            if (savedID !== null) {
                element.id = savedID;
            }
            return (foundElm) ? false : true;
        };
    window.onload = function () {
        var image = document.getElementById("demo");
        console.log('undefined', (typeof image === 'undefined') ? true : false); // false
        console.log('null', (image === null) ? true : false); // false
        console.log('find-by-id', isNull(image)); // false
        image.parentNode.removeChild(image);
        console.log('undefined', (typeof image === 'undefined') ? true : false); // false ~ should be true?
        console.log('null', (image === null) ? true : false); // false ~ should be true?
        console.log('find-by-id', isNull(image)); // true ~ correct but there must be a better way than this?
    };
    </script>
</head>
<body>
    <div id="demo"></div>
</body>
</html>

Zasadniczo powyższy kod demonstruje element przechowywany w zmiennej, a następnie usuwany z DOM. Pomimo tego, że element został usunięty z DOM, zmienna zachowuje element tak, jak był po raz pierwszy zadeklarowany. Innymi słowy, nie jest to żywe odniesienie do samego elementu, ale raczej replika. W rezultacie sprawdzenie wartości zmiennej (elementu) pod kątem istnienia zapewni nieoczekiwany wynik.

isNullFunkcja jest moja próba sprawdzenia dla istnienia elementów ze zmiennej, i to działa, ale chciałbym wiedzieć, czy istnieje prostszy sposób, aby osiągnąć ten sam rezultat.

PS: Interesuje mnie również, dlaczego zmienne JavaScript zachowują się w ten sposób, jeśli ktoś wie o dobrych artykułach związanych z tym tematem.

Justin Bull
źródło
18
W rzeczywistości jest to żywe odniesienie do samego elementu, po prostu nie ma go już w dokumencie. Ta funkcjonalność jest wymagana, ponieważ można wyciągnąć element z DOM, a następnie włożyć go z powrotem z wszystkimi modułami obsługi zdarzeń / etc, które nadal są do niego dołączone. A dlaczego zmienne JS tak działają? Ponieważ byłoby to niezwykle denerwujące, gdyby tego nie zrobili. JS usuwa zmienne tylko wtedy, gdy nie masz już ŻADNYCH odniesień do nich. Język nie ma sposobu, aby dowiedzieć się, które odniesienia uważasz za ważne, a które uważasz za bezwartościowe.
Mark Kahn
@cwolves Ciekawe. Spotkałem się z tym wiele razy i nigdy tak naprawdę o tym nie myślałem. W rzeczywistości w moim bieżącym projekcie zapisuję elementy w tablicy, zanim wprowadzę w nich jakiekolwiek zmiany, na wypadek, gdy chcę je cofnąć.
Justin Bull
1
Odśmiecanie jest uruchamiane od czasu do czasu i usuwa wszystko, co według niego może. Wydaje się dość kiepski w większości przeglądarek, ale staje się coraz lepszy, ponieważ programiści zdają sobie sprawę, że niektóre przeglądarki działają przez kilka dni lub tygodni między restartami, więc dobre wyrzucanie elementów bezużytecznych jest kluczowe dla wydajności przeglądarki. Programiści WWW mogą pomóc, usuwając niepotrzebne właściwości (a zatem odniesienia do rzeczy w pamięci).
RobG
2
@JustinBull należy zachować ostrożność podczas przechowywania kopii elementów do przywrócenia. Podczas przechowywania elementu DOM w tablicy przechowywane jest odwołanie do elementu DOM, a nie jego kopia, więc zmiany wprowadzone w elemencie DOM zostaną odzwierciedlone podczas odwoływania się do elementu tablicy. Tak jest w przypadku wszystkich obiektów w javascript (zmienne typu „object”).
Anthony DiSanti,

Odpowiedzi:

545

Wygląda na to, że niektórzy lądują tutaj i po prostu chcą wiedzieć, czy istnieje element (nieco inny niż pierwotne pytanie).

To tak proste, jak użycie dowolnej metody wyboru przeglądarki i sprawdzenie jej prawdziwej wartości (ogólnie).

Na przykład, jeśli mój żywioł mieliśmy idz "find-me", mogę po prostu użyć ...

var elementExists = document.getElementById("find-me");

Jest to określone, aby zwrócić odwołanie do elementu lub null. Jeśli musisz mieć wartość logiczną, po prostu rzuć a !!przed wywołaniem metody.

Ponadto możesz użyć niektórych z wielu innych metod wyszukiwania elementów, takich jak (wszystkie żyjące document):

  • querySelector()/querySelectorAll()
  • getElementsByClassName()
  • getElementsByName()

Niektóre z tych metod zwracają a NodeList, dlatego należy sprawdzić jej lengthwłaściwość, ponieważ a NodeListjest obiektem, a zatem jest prawdą .


Aby faktycznie ustalić, czy element istnieje jako część widocznego DOM (podobnie jak pierwotnie zadane pytanie), Csuwldcat zapewnia lepsze rozwiązanie niż tworzenie własnych (jak kiedyś zawierała ta odpowiedź). Oznacza to, że do korzystania zcontains() metody na elementach DOM.

Możesz użyć go tak ...

document.body.contains(someReferenceToADomElement);
alex
źródło
1
Właśnie tego szukałem! Więc oczywiście lol, dlaczego o tym nie pomyślałem. Czy znasz też jakieś dobre artykuły wyjaśniające, dlaczego zmienne działają w ten sposób?
Justin Bull
3
Jeszcze krótszy:var elementInDom = function( el ) { while ( el = el.parentNode ) if ( el === document ) return true; return false; }
bennedich
2
@ButtleButkus Przeczytaj aktualne pytanie. Takie rozwiązanie użyłeś nie ma sensu jak getElementById() będzie zwracać referencję do elementu DOM lub nullw związku z użyciem typeof(szczególnie na RHS) jest niewłaściwy (jeśli nie zostały zdefiniowane, warunek LHS będzie rzucać ReferenceError).
alex
2
Czy jest jakiś powód, aby używać tego w stosunku do tego, co zostało opublikowane poniżej: document.body.contains()które wydaje się mieć bardzo dobrą obsługę przeglądarki?
zmiażdżyć
1
@Jonz Usunięto starą część odpowiedzi, nie zapomnij iść i zagłosować csuwldcat
Alex
310

Użyj, getElementById()jeśli jest dostępny.

Oto prosty sposób, aby to zrobić za pomocą jQuery:

if ($('#elementId').length > 0) {
  // Exists.
}

A jeśli nie możesz używać bibliotek stron trzecich, po prostu trzymaj się JavaScript:

var element =  document.getElementById('elementId');
if (typeof(element) != 'undefined' && element != null)
{
  // Exists.
}
Kon
źródło
2
W przypadku projektu, nad którym pracuję, nie mogę korzystać z biblioteki. Dobry, surowy kod tylko w modzie. Jestem świadomy tej metody jQuery, ale nie działa ona na elementy niezawinięte w kontenerze jQuery. Na przykład $('#elementId')[0].lengthnie dałoby tego samego wyniku.
Justin Bull
8
Czy istnieje jakikolwiek dobry powód tak skomplikowanej instrukcji if w drugim przykładzie kodu? Dlaczego nie po prostu if (element) {}? Jeśli element jest niezdefiniowany lub ma wartość NULL, to wyrażenie ma wartość fałsz. Jeśli element jest elementem DOM, wówczas wyrażenie jest prawdziwe.
kayahr 18.12.12
2
@kayahr To jest zbyt skomplikowane. getElementById()jest zwracany, nulljeśli nie znalazł elementu, więc sprawdzenie, czy rzeczywiście została zwrócona wartość, jest wszystkim, czego potrzeba.
alex
5
Myślę, że to tylko zdrowy rozsądek.
Kon
8
getElementByIdnigdy nie powinien wracać undefined. W każdym razie element != nullczek mógłby to odebrać.
191

Za pomocą Node.contains DOM API możesz dość łatwo sprawdzić obecność dowolnego elementu na stronie (obecnie w DOM):

document.body.contains(YOUR_ELEMENT_HERE);

UWAGA : PRZEGLĄDARKA : documentobiekt w Internet Explorerze nie ma contains()metody - aby zapewnić kompatybilność z różnymi przeglądarkami, użyj document.body.contains()zamiast tego.

csuwldcat
źródło
4
To wydaje się być ostateczną odpowiedzią na ten problem ... i jego wsparcie, jeśli wierzyć MDN, jest całkiem dobre.
zmiażdżyć
2
To najlepsza odpowiedź. Pamiętaj, że samo sprawdzenie document.contains()powinno wystarczyć.
alex
@csuwldcat To zadziałało dla mnie, przynajmniej w Chrome z document.contains(document.documentElement). documentma Nodena swoim łańcuchu prototypów, o ile mogę powiedzieć ( document-> HTMLDocument-> Document-> Node)
alex
4
To jest rzeczywiście najlepsza odpowiedź: - jest standardem internetowym - jest bardzo dobrze obsługiwany (nieco zaskakująco nie pojawia się w Firefoksie do wersji 9, tak sądzę, ponieważ była to niestandardowa funkcja wymyślona w IE, która nie była ustandaryzowany do później) - musi być najszybszy, ponieważ wykorzystuje pojedyncze wywołanie do natywnego API
Jon z
2
@LeeSaxon Składnia jest document.body.contains([selector]), tj.document.body.contains(document.getElementById('div')
iglesiasedd
67

Po prostu robię:

if(document.getElementById("myElementId")){
    alert("Element exists");
} else {
    alert("Element does not exist");
}

Działa dla mnie i nie miałem z tym żadnych problemów ...

Anomalia
źródło
1
Nie ma to jednak nic wspólnego z pierwotnym pytaniem. OP chce wiedzieć, czy odwołanie do elementu DOM jest częścią widocznego DOM, czy nie.
alex
16
Pomógł mi jednak. Szukałem prostego testu istnienia elementu; to zadziałało. Dzięki.
khaverim
1
Ta odpowiedź działa dobrze, ale tylko wtedy, gdy element ma id. Lepsze rozwiązanie, które odpowiada na pytanie Jak sprawdzić, czy element istnieje w widocznym DOM? z dowolnym elementem, wystarczą nawet elementy bez ids document.body.contains(element).
Edward,
@Edward To jest coś zupełnie innego niżcontains()
alex
Rozumiem. W swoim komentarzu sugerowałem tylko, że inne odpowiedzi są lepsze i lepiej pasują do pytania.
Edward
11

Możesz po prostu sprawdzić, czy właściwość parentNode ma wartość NULL.

To jest,

if(!myElement.parentNode)
{
    // The node is NOT in the DOM
}
else
{
    // The element is in the DOM
}
mikechambers
źródło
Wiem, że to stare pytanie, ale ta odpowiedź jest dokładnie eleganckim i prostym rozwiązaniem na pytanie, którego szukałem.
poby
11
@poby: Może wydawać się elegancki, ale tak naprawdę nie robi tego, o co prosił. Sprawdza tylko, czy element ma element nadrzędny. Nie oznacza to, że element znajduje się w widocznym DOM, ponieważ być może element nadrzędny nie jest z nim połączony.
kayahr
Trzeba będzie przejść przez wszystkich rodziców rodziców, aby dowiedzieć się, czy ostatni jest dokumentem. Innym problemem jest to, że nadal może znajdować się poza widocznym zasięgiem, być zakryty lub być niewidoczny z wielu innych powodów.
Arek Bal
Element może również mieć element parentNode tylko dlatego, że został dołączony do fragmentu dokumentu.
11

Z sieci deweloperów Mozilla :

Ta funkcja sprawdza, czy element znajduje się w treści strony. Ponieważ zawiera () jest włącznie i ustalenie, czy treść zawiera się nie jest intencją isInPage, ten przypadek wyraźnie zwraca wartość false.

function isInPage(node) {
  return (node === document.body) ? false : document.body.contains(node);
}

węzeł to węzeł, który chcemy sprawdzić w <body>.

Ekramul Hoque
źródło
+1, czy to działa również w przypadku (dowolnych) węzłów tekstowych (lub węzłów komentarzy)?
Nikos M.
@NikosM. Powinien działać w dowolnym tagu HTML, ale go nie testowałem.
Ekramul Hoque
4
Nie powinno falsebyć true?
Marc-André Lafortune
Jeśli nodeIS jest document.body, z pewnością metoda powinna zwrócić true? Tj.return (node === document.body) || document.body.contains(node);
daiscog,
7

Najłatwiejszym rozwiązaniem jest sprawdzenie właściwości baseURI , która jest ustawiana tylko wtedy, gdy element jest wstawiany do DOM, i wraca do pustego ciągu po usunięciu.

var div = document.querySelector('div');

// "div" is in the DOM, so should print a string
console.log(div.baseURI);

// Remove "div" from the DOM
document.body.removeChild(div);

// Should print an empty string
console.log(div.baseURI);
<div></div>

Peter Mortensen
źródło
5
Nawet nie wiedziałem, że w węzłach DOM istnieje właściwość baseURI. W tym podejściu podoba mi się to, że używa właściwości samego elementu, co prawdopodobnie oznacza, że ​​działałoby, nawet jeśli element znajduje się w innym dokumencie (np. Iframe). Nie podoba mi się to, że nie działa poza Webkit.
DoctorDestructo
Uważaj, jak to rzuci się następujący błąd, jeśli element nie znajduje się w dokumencie: Cannot read property 'baseURI' of null. Przykład:console.log(document.querySelector('aside').baseURI)
Ian Davis
Nie można użyć tej metody, ponieważ zawsze drukuje ona ten sam ciąg znaków, co obecnie.
Kagami Sascha Rosylight
4

Rozwiązanie jQuery:

if ($('#elementId').length) {
    // element exists, do something...
}

To działało dla mnie przy użyciu jQuery i nie wymagało $('#elementId')[0]użycia.

Code Buster
źródło
Dlaczego $('#elementId')[0]czegoś należy unikać?
alex
Długo odpowiedziałem na to pytanie, więc używając $ ('# elementId') [0] Wierzę, że zawsze wskazujesz, że wartość będzie na 0. indeksie. W ten sposób zawsze sprawdzasz pierwszy występujący element. Co to jest wiele pól wyboru o tej samej nazwie, więc jak przycisk opcji. Tym razem długość będzie pomocna.
Code Buster
3

Rozwiązanie csuwldcat wydaje się być najlepszym z tego grona, ale potrzebna jest niewielka modyfikacja, aby działał poprawnie z elementem znajdującym się w innym dokumencie niż kod JavaScript, takim jak iframe:

YOUR_ELEMENT.ownerDocument.body.contains(YOUR_ELEMENT);

Zwróć uwagę na użycie właściwości elementu ownerDocument, w przeciwieństwie do zwykłego starego document(który może, ale nie musi odnosić się do dokumentu właściciela elementu).

torazaburo opublikowało jeszcze prostszą metodę, która działa również z elementami nielokalnymi, ale niestety wykorzystuje baseURIwłaściwość, która w tej chwili nie jest jednolicie zaimplementowana w przeglądarkach (mogłem ją uruchomić tylko w oparciu o WebKit ). Nie mogłem znaleźć innych właściwości elementu lub węzła, które mogłyby być użyte w podobny sposób, więc myślę, że na razie powyższe rozwiązanie jest tak dobre, jak to możliwe.

DoctorDestructo
źródło
3

Zamiast iterujących rodziców, możesz po prostu uzyskać prostokąt ograniczający, który jest zerami, gdy element jest odłączony od DOM:

function isInDOM(element) {
    if (!element)
        return false;
    var rect = element.getBoundingClientRect();
    return (rect.top || rect.left || rect.height || rect.width)?true:false;
}

Jeśli chcesz obsłużyć przypadek krawędzi elementu o zerowej szerokości i wysokości w punkcie zero u góry i zero w lewo, możesz dwukrotnie sprawdzić, powtarzając rodziców, aż document.body:

function isInDOM(element) {
    if (!element)
        return false;
    var rect = element.getBoundingClientRect();
    if (element.top || element.left || element.height || element.width)
        return true;
    while(element) {
        if (element == document.body)
            return true;
        element = element.parentNode;
    }
    return false;
}
Erez Pilosof
źródło
Powoduje to zmianę układu: gist.github.com/paulirish/5d52fb081b3570c81e3a#box-metrics
Steven Vachon
3

Prosty sposób sprawdzenia, czy element istnieje, można wykonać za pomocą jednowierszowego kodu jQuery.

Oto kod poniżej:

if ($('#elementId').length > 0) {
    // Do stuff here if the element exists
} else {
    // Do stuff here if the element does not exist
}
Ravi Agrawal
źródło
2

Inną opcją jest element.closest :

element.closest('body') === null
Brian M. Hunt
źródło
2

Ten kod działa dla mnie i nie miałem z nim żadnych problemów.


    if(document.getElementById("mySPAN")) {
        // If the element exists, execute this code
        alert("Element exists");
    }
    else {
        // If the element does not exist execute this code
        alert("Element does not exists");
    }
Mohammad Ayoub Khan
źródło
1

Możesz także użyć jQuery.contains, który sprawdza, czy element jest potomkiem innego elementu. Przeszedłem documentjako element nadrzędny do wyszukiwania, ponieważ wszelkie elementy, które istnieją na stronie DOM, są potomkami document.

jQuery.contains( document, YOUR_ELEMENT)
nitinkhurany
źródło
1

Sprawdź, czy element jest dzieckiem <html>poprzez Node::contains():

const div = document.createElement('div');
document.documentElement.contains(div); //-> false

document.body.appendChild(div);
document.documentElement.contains(div); //-> true

Omówiłem to i więcej w is-dom-odłączony .

Steven Vachon
źródło
1

Proste rozwiązanie z jQuery:

$('body').find(yourElement)[0] != null
mateusmaso
źródło
2
... lub$(document).find(yourElement).length !== 0
Grinn
1
To wykorzystuje to null == undefined. Rzeczywista zwrócona wartość to undefined. Porównywanie tego nulljest trochę dziwne.
alex
1
// This will work prefectly in all :D
function basedInDocument(el) {

    // This function is used for checking if this element in the real DOM
    while (el.parentElement != null) {
        if (el.parentElement == document.body) {
            return true;
        }
        el = el.parentElement; // For checking the parent of.
    } // If the loop breaks, it will return false, meaning
      // the element is not in the real DOM.

    return false;
}
qandil afa
źródło
W sumie co? Wszystkie przypadki?
Peter Mortensen
1
  • Jeśli element znajduje się w DOM , jego rodzice również powinni być w
  • I ostatnim dziadkiem powinien być document

Aby sprawdzić, czy po prostu zapętlamy parentNodedrzewo drzewa, aż dotrzemy do ostatniego dziadka

Użyj tego:

/**
 * @param {HTMLElement} element - The element to check
 * @param {boolean}     inBody  - Checks if the element is in the body
 * @return {boolean}
 */
var isInDOM = function(element, inBody) {
    var _ = element, last;

    while (_) {
        last = _;
        if (inBody && last === document.body) { break;}
        _ = _.parentNode;
    }

    return inBody ? last === document.body : last === document;
};
silassare
źródło
2
To może być najlepsza odpowiedź, ponieważ nie powoduje żadnego ponownego renderowania w DOM.
Steven Vachon
Wyjaśnienie byłoby w porządku (odpowiedz, edytując odpowiedź , a nie tutaj w komentarzach).
Peter Mortensen
0

Podobało mi się to podejście:

var elem = document.getElementById('elementID');

if (elem)
    do this
else
    do that

Również

var elem = ((document.getElementById('elemID')) ? true:false);

if (elem)
    do this
else
    do that
Hugh
źródło
1
Dlaczego nie tylko, !!jeśli chcesz logicznego?
alex
Więc jeśli element nie ma identyfikatora, to uważa się, że nie ma go w DOM? Powiedziałbym, że to źle.
Steven Vachon,
0

Użyj querySelectorAllz forEach,

document.querySelectorAll('.my-element').forEach((element) => {
  element.classList.add('new-class');
});

w przeciwieństwie do:

const myElement = document.querySelector('.my-element');
if (myElement) {
  element.classList.add('new-class');
}
Rafał Enden
źródło
0

Spróbuj wykonać następujące czynności. Jest to najbardziej niezawodne rozwiązanie:

window.getComputedStyle(x).display == ""

Na przykład,

var x = document.createElement("html")
var y = document.createElement("body")
var z = document.createElement("div")
x.appendChild(y);
y.appendChild(z);

z.style.display = "block";

console.log(z.closest("html") == null); // 'false'
console.log(z.style.display); // 'block'
console.log(window.getComputedStyle(z).display == ""); // 'true'
Dexiang
źródło
1
Prawdopodobnie powoduje to zmianę układu: gist.github.com/paulirish/5d52fb081b3570c81e3a#getcomputedstyle
Steven Vachon
0

Wszystkie istniejące elementy mają zestaw parentElement, z wyjątkiem elementu HTML!

function elExists (e) { 
    return (e.nodeName === 'HTML' || e.parentElement !== null);
};
Jonasz
źródło
Czy zawsze jest to „HTML” ? Czy to może być „html” ?
Peter Mortensen
x.tagName lub x.nodeName zawsze wielkimi literami bez względu na to, jak piszesz to w kodzie
Jonah
0

ten stan kurcząt wszystkie przypadki.

function del() {
//chick if dom has this element 
//if not true condition means null or undifind or false .

if (!document.querySelector("#ul_list ")===true){

// msg to user
    alert("click btn load ");

// if console chick for you and show null clear console.
    console.clear();

// the function will stop.
    return false;
}

// if its true function will log delet .
console.log("delet");

}

Omar Bakhsh
źródło
0

Wolę korzystać z tej node.isConnectedwłaściwości ( odwiedź MDN ).

Uwaga: Zwróci wartość true, jeśli element zostanie również dołączony do ShadowRoot, co może nie być pożądane przez wszystkich.

Przykład:

const element = document.createElement('div');
console.log(element.isConnected); // Returns false
document.body.append(element);
console.log(element.isConnected); // Returns true
Robbendebiene
źródło