Як я можу перевірити, чи існує елемент у видимій DOM?


421

Як ви протестуєте елемент на існування без використання getElementByIdметоду?

Я створив демо-версію для довідки. Я також надрукую тут код:

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

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

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

PS: Мене також цікавить, чому змінні JavaScript так поводяться, якщо хтось знає якісь хороші статті, пов'язані з даною темою.


18
Насправді це пряма посилання на сам елемент, просто це вже не в документі. Ця функціональність потрібна, оскільки ви можете фактично витягнути елемент з DOM, а потім повернути його згодом із усіма обробниками подій / тощо, які все ще додаються до нього. Що стосується того, чому змінні JS діють так? Бо було б неймовірно прикро, якби вони цього не зробили. JS видаляє змінні лише тоді, коли ви більше не маєте жодних посилань на них. Мова не може знати, які посилання ви вважаєте важливими, а які ви вважаєте марними.
Марк Кан

@cwolves Цікаво. Я раніше з цим стикався багато разів і ніколи насправді не думав багато про це. Насправді в моєму поточному проекті я зберігаю елементи в масиві, перш ніж вносити в них будь-які зміни, на всякий випадок, якщо я хочу відновити зміни.
Джастін Булл

1
Збір сміття час від часу працює і видаляє все, що він думає, що може. У більшості браузерів це виглядає досить паршиво, але стає кращим, оскільки розробники розуміють, що деякі браузери працюють протягом днів або тижнів між перезавантаженнями, тому хороша збирання сміття є життєво важливою для роботи браузера. Веб-розробники можуть допомогти, видаливши властивості (а отже, посилання на речі в пам'яті), які більше не потрібні.
RobG

2
@JustinBull будьте обережні зі зберіганням копій елементів для відновлення. Під час зберігання елемента DOM в масиві зберігається посилання на елемент DOM, а не копія, тому зміни, внесені до елемента DOM, будуть відображені при посиланні на елемент масиву. Це стосується всіх об'єктів у javascript (змінні типу 'object').
Ентоні Дісанті

Відповіді:


545

Здається, що деякі люди тут приземляються, і просто хочуть дізнатись, чи існує якийсь елемент (дещо інший за оригінальним питанням).

Це так само просто, як використання будь-якого методу вибору браузера та перевірка його на предмет трибунної цінності (як правило).

Наприклад, якщо мій елемент мав idз "find-me", я міг би просто використовувати ...

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

Це вказується або повертає посилання на елемент або null. Якщо у вас має бути булеве значення, просто киньте a !!перед викликом методу.

Крім того, ви можете використовувати деякі з багатьох інших методів, які існують для пошуку елементів, таких як (все живе document)

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

Деякі з цих методів повертають a NodeList, тому не забудьте перевірити його lengthвластивість, тому що a NodeListє об'єктом, а отже, і правдою .


Для того, щоб фактично визначити, чи існує елемент як частина видимого DOM (на зразок питання, яке було задано спочатку), Csuwldcat пропонує краще рішення, ніж прокручування власного (як ця відповідь раніше містила). Тобто, щоб використовувати вcontains() метод за елементами DOM.

Ви можете використовувати його так ...

document.body.contains(someReferenceToADomElement);

1
Саме те, що я шукав! Так очевидно, хаха, чому я не подумав про це. Також, чи знаєте ви якісь хороші статті, які пояснюють, чому змінні діють так?
Джастін Булл

3
Ще коротше:var elementInDom = function( el ) { while ( el = el.parentNode ) if ( el === document ) return true; return false; }
bennedich

2
@ButtleButkus Прочитайте власне питання. Це рішення , яке ви використовували не має сенсу , так як getElementById() буде повертати посилання на DOM - елемент або null, тому, використовуючи typeof(особливо на РІТ) є неправильним (якщо він не визначений, то умова LHS б кинути ReferenceError).
алекс

2
Чи є якась причина використовувати це над тим, що було розміщено нижче: document.body.contains()який, здається, має дуже гарну підтримку браузера?
розчавити

1
@Jonz Видалив стару частину відповідей, не забудьте піти і проголосувати csuwldcat
alex

310

Використовуйте, getElementById()якщо є.

Також ось простий спосіб зробити це за допомогою jQuery:

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

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

var element =  document.getElementById('elementId');
if (typeof(element) != 'undefined' && element != null)
{
  // Exists.
}

2
Для проекту, над яким я працюю, я не в змозі використовувати бібліотеку. Тільки необроблений код моди. Мені відомо про цей метод jQuery, але він не працює на елементах, не загорнутих у контейнер jQuery. Наприклад, $('#elementId')[0].lengthне дав би однакового результату.
Джастін Булл

8
Чи є якась вагома причина для такого складного, якщо вислів у другому прикладі коду? Чому б не просто if (element) {}? Якщо елемент не визначений або нульовий, то цей вираз є помилковим. Якщо елемент є елементом DOM, то вираз вірно.
kayahr

2
@kayahr Це занадто складно. getElementById()spec'd повернути, nullякщо він не знайшов елемент, тому перевірка на повернене значення truthy - це все, що потрібно.
алекс

5
Я думаю, що це просто здоровий глузд.
Кон,

8
getElementByIdніколи не повинні повертатися undefined. У будь-якому випадку, element != nullчек забрав би це.

191

Використовуючи DOM API Node.contains , ви можете досить легко перевірити наявність будь-якого елемента на сторінці (на даний момент у DOM):

document.body.contains(YOUR_ELEMENT_HERE);

ПРИМІТКА CROSS-BROWSER : documentоб’єкт в Internet Explorer не має contains()методу - щоб забезпечити сумісність між браузерами, використовуйте document.body.contains()натомість.


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

2
Це найкраща відповідь. Зауважте, що лише перевірки document.contains()повинно бути достатньо.
alex

@csuwldcat Це працювало для мене, принаймні, в Chrome з document.contains(document.documentElement). documentдійсно має Nodeна своїй ланцюжку прототипів, наскільки я можу сказати ( document-> HTMLDocument-> Document-> Node)
Alex

4
Це дійсно найкраща відповідь: - це веб-стандарт - він дуже добре підтримується (дещо дивно, що він з'являється у Firefox до версії 9, я здогадуюсь, тому що це була нестандартна функція, придумана в IE, яка не була стандартизовано до пізніше) - він повинен бути найшвидшим, оскільки він використовує один виклик до рідного API
Jon z

2
@LeeSaxon Синтаксис є document.body.contains([selector]), тобтоdocument.body.contains(document.getElementById('div')
iglesiasedd

67

Я просто роблю:

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

Він працює на мене і не мав до цього жодних проблем ...


1
Це, однак, не має нічого спільного з оригінальним питанням. ОП хоче знати, чи посилання на елемент DOM є частиною видимого DOM чи ні.
alex

16
Допомогли мені, хоча. Я шукав просту перевірку існування елементів; це спрацювало. Дякую.
хаверим

1
Ця відповідь працює добре, але лише тоді, коли в елемента є id. Краще рішення, яке відповідає на питання Як перевірити, чи існує елемент у видимій DOM? з будь-яким елементом, навіть елементи без ids робити document.body.contains(element).
Едвард

@Edward Це щось зовсім іншеcontains()
alex

Я це розумію. Я просто запропонував у своєму коментарі, що інші відповіді краще і більше відповідають на питання.
Едвард

11

Ви можете просто перевірити, чи є властивість parentNode нульовою.

Це є,

if(!myElement.parentNode)
{
    // The node is NOT in the DOM
}
else
{
    // The element is in the DOM
}

Я знаю, що це давнє запитання, але ця відповідь є саме таким елегантним простим рішенням питання, який я шукав.
poby

11
@poby: Це може здатися елегантним, але він насправді не робить те, що просили Він перевіряє лише наявність у елемента батьківського елемента. Це не означає, що елемент знаходиться у видимій DOM, оскільки, можливо, батьківський елемент не підключений до нього.
kayahr

Треба було б пройти через усіх батьків батьків, щоб з’ясувати, чи є останнім документом. Інша проблема полягає в тому, що вона все ще може знаходитися поза видимим діапазоном, бути прикритою або бути невидимою через багато інших причин.
Арек Бал

Елемент також може мати батьківський вузол лише внаслідок додавання до фрагменту документа.

11

Від мережі розробників Mozilla :

Ця функція перевіряє, чи є елемент в тілі сторінки. Оскільки містить () включно і визначає, чи містить сам організм не намір isInPage, цей випадок явно повертає помилку.

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

вузол - це вузол, який ми хочемо перевірити в <body>.


+1, чи працює це для (довільних) текстових вузлів (або вузлів коментарів)?
Нікос М.

@NikosM. Він повинен працювати в будь-якому тезі html, але я його не перевіряв.
Ekramul Hoque

4
Не повинно falseбути true?
Марк-Андре Лафортун

Якщо nodeIS - це document.body, безумовно, метод повинен повернутися true? Тобто,return (node === document.body) || document.body.contains(node);
дайског

7

Найпростішим рішенням є перевірка властивості baseURI , яка встановлюється лише тоді, коли елемент вставлений у DOM, і він повертається до порожнього рядка при його видаленні.

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>


5
Я навіть не знав, що на вузлах DOM існує властивість baseURI. Що мені подобається в цьому підході, це те, що він використовує властивість самого елемента, що, імовірно, означає, що він би працював, навіть якщо елемент знаходиться в іншому документі (наприклад, iframe). Що мені не подобається в тому, що він, схоже, не працює за межами Webkit.
DoctorDestructo

Ретельна , як це викличе таку помилку , якщо елемент не є в документі: Cannot read property 'baseURI' of null. Приклад:console.log(document.querySelector('aside').baseURI)
Іван Девіс

Цей метод не можна використовувати, оскільки він завжди друкує ту саму рядок, що і зараз.
Kagami Sascha Rosylight

4

jQuery рішення:

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

Це працювало для мене за допомогою jQuery, і його не потрібно $('#elementId')[0]було використовувати.


Чому $('#elementId')[0]чогось слід уникати?
alex

Я довго відповів на це, Отже, використовуючи $ ('# elementId') [0] Я вважаю, що ви завжди вказуєте на те, що значення буде в 0-му індексі. Таким чином, ви завжди перевіряєте наявність першого елемента, що виникає. Що там було декілька прапорців з такою ж назвою, так, як радіо-кнопка. У цей час .length буде корисним.
Код Бастер

3

Рішення csuwldcat, здається, найкраще, але потрібна незначна модифікація, щоб змусити її правильно працювати з елементом, який міститься в іншому документі, ніж працює код JavaScript, наприклад, iframe:

YOUR_ELEMENT.ownerDocument.body.contains(YOUR_ELEMENT);

Зверніть увагу на використання властивості елемента на ownerDocumentвідміну від простого старого document(яке може або не може посилатися на документ власника елемента).

torazaburo опублікував ще простіший метод, який також працює з нелокальними елементами, але, на жаль, він використовує baseURIвластивість, яка наразі не рівномірно реалізована у веб-переглядачах (я могла змусити його працювати лише на веб-базі WebKit ). Я не міг знайти жодних інших властивостей елемента чи вузла, які можна було б використати аналогічно, тому, на даний момент, я думаю, що вищевказане рішення є настільки ж хорошим, як і отримується.


3

Замість ітерації батьків, ви можете просто отримати обмежуючий прямокутник, який є всіма нулями, коли елемент від'єднаний від DOM:

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

Якщо ви хочете обробити край крайнього елемента нульової ширини та висоти в нульовому верхньому та нульовому лівому напрямку, ви можете двічі перевірити, повторивши батьків до 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;
}

Це спричиняє перестановку: gist.github.com/paulirish/5d52fb081b3570c81e3a#box-metrics
Стівен

3

Простий спосіб перевірити, чи існує елемент, можна виконати через однорядковий код jQuery.

Ось код нижче:

if ($('#elementId').length > 0) {
    // Do stuff here if the element exists
} else {
    // Do stuff here if the element does not exist
}


2

Цей код працює для мене, і я не мав жодних проблем з ним.


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

1

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

jQuery.contains( document, YOUR_ELEMENT)

1

Перевірте, чи елемент є дочірнім <html>через Node::contains():

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

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

Я висвітлював це і багато іншого в ізоляторі .


1

Просте рішення з jQuery:

$('body').find(yourElement)[0] != null

2
... або$(document).find(yourElement).length !== 0
Грінн

1
Це експлуатує null == undefined. Реальне повернене значення було б undefined. Порівнювати це проти null- трохи дивно.
алекс

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

У всьому чому? Усі справи?
Пітер Мортенсен

1
  • Якщо елемент знаходиться в DOM , його батьки також повинні бути в
  • І останнім бабусею і дідусем повинен бути той document

Отже, щоб перевірити, що ми просто прив'язуємо до елемента parentNode дерева поки не дійдемо до останнього бабусі та дідуся

Використовуй це:

/**
 * @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;
};

2
Це може бути найкращою відповіддю, оскільки це не викликає повторного відображення в DOM.
Стівен Вахон

Пояснення буде в порядку (відповідайте, редагуючи свою відповідь , а не тут у коментарях).
Пітер Мортенсен

0

Мені сподобався такий підхід:

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

if (elem)
    do this
else
    do that

Також

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

if (elem)
    do this
else
    do that

1
Чому б не просто, !!якщо хочете булевого?
alex

Отже, якщо елемент не має ідентифікатора, то вважається, що він не знаходиться в DOM? Я б сказав, що це неправильно.
Стівен Вахон

0

Використовуйте querySelectorAllз forEach,

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

як протилежне:

const myElement = document.querySelector('.my-element');
if (myElement) {
  element.classList.add('new-class');
}

0

Спробуйте наступне. Це найнадійніше рішення:

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

Наприклад,

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'

1
Це, ймовірно, спричиняє перестановку: gist.github.com/paulirish/5d52fb081b3570c81e3a#getcomputedstyle
Стівен

0

Усі існуючі елементи мають набір parentElement, за винятком елемента HTML!

function elExists (e) { 
    return (e.nodeName === 'HTML' || e.parentElement !== null);
};

Це завжди "HTML" ? Чи може це бути "html" ?
Пітер Мортенсен

x.tagName або x.nodeName завжди у великому регістрі немає матери, як ви це записуєте у своєму коді
Jonah

0

ця стан пташеня всі випадки.

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");

}


0

Я вважаю за краще використовувати node.isConnectedмайно ( відвідати MDN ).

Примітка. Це повернеться істинним, якщо елемент також буде доданий до ShadowRoot, який може не бути всіма бажаними способами поведінки.

Приклад:

const element = document.createElement('div');
console.log(element.isConnected); // Returns false
document.body.append(element);
console.log(element.isConnected); // Returns true
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.