Как я могу проверить, существует ли элемент в видимом DOM?


423

Как вы проверяете элемент на существование без использования 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 (переменные типа «объект»).
Энтони ДиСанти

Ответы:


545

Кажется , что некоторые люди приземляются здесь, и просто хотят знать , если элемент существует (немного по- другому к исходному вопросу).

Это так же просто, как использовать любой из методов выбора браузера и проверить его на истинное значение (как правило).

Например, если бы у моего элемента был idof "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; }
Беннедич

2
@ButtleButkus Читайте актуальный вопрос. То решение, которое вы использовали, не имеет смысла, так как getElementById() будет возвращать ссылку на элемент DOM или null, следовательно, использование typeof(особенно в RHS) является неправильным (если оно не было определено, условие LHS выдает a 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 во втором примере кода? Почему не просто if (element) {}? Когда элемент не определен или равен нулю, тогда это выражение ложно. Если элемент является элементом DOM, то выражение является истинным.
Каяр

2
@kayahr Это слишком сложно. getElementById()is spec'd для возврата, nullесли элемент не найден , поэтому проверка на истинное возвращаемое значение - это все, что нужно.
Алекс

5
Я думаю, что это просто здравый смысл.
Кон

8
getElementByIdникогда не должен возвращаться undefined. В любом случае, element != nullчек подхватит это.

191

Используя Node.contains DOM API , вы можете легко проверить наличие любого элемента на странице (в настоящее время в DOM):

document.body.contains(YOUR_ELEMENT_HERE);

ПРИМЕЧАНИЕ : у documentобъекта в Internet Explorer нет contains()метода - для обеспечения кросс-браузерной совместимости используйте document.body.contains()вместо этого.


4
Это похоже на окончательный ответ на эту проблему ... и его поддержка, если верить MDN, довольно хороша.
раздавить

2
Это лучший ответ. Обратите внимание, что достаточно просто проверить document.contains().
Алекс

@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

68

Я просто делаю:

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

Это работает для меня и не было проблем с этим еще ...


1
Это не имеет ничего общего с первоначальным вопросом. ОП хочет знать, является ли ссылка на элемент DOM частью видимого DOM или нет.
Алекс

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, потому что, возможно, родительский элемент не связан с ним.
каяр

Нужно пройти через всех родителей родителей, чтобы узнать, является ли последний документ. Другая проблема заключается в том, что он все еще может находиться за пределами видимого диапазона или быть скрытым или невидимым по многим другим причинам.
Арек Бал

Элемент также может иметь parentNode только благодаря тому, что он был добавлен к фрагменту документа.

11

Из Сети разработчиков Mozilla :

Эта функция проверяет, находится ли элемент в теле страницы. Так как метод Вектор () является включающим, и определение того, содержит ли тело себя, не предназначено для isInPage, в этом случае явно возвращается значение false.

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

узел - это узел, который мы хотим проверить в <теле>.


+1, это работает также для (произвольных) текстовых узлов (или узлов комментариев)?
Никос М.

@NikosM. Он должен работать в любом HTML-теге, но я не проверял его.
Экрамул Хок,

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.
Доктор Деструкто

Тщательная , как это вызовет следующую ошибку , если элемент не является в документе: Cannot read property 'baseURI' of null. Пример:console.log(document.querySelector('aside').baseURI)
Ян Дэвис

Этот метод нельзя использовать, поскольку он всегда печатает ту же строку, что и сейчас.
Кагами Саша Розайлайт

4

Решение jQuery:

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

Это работало для меня с использованием jQuery и не требовало $('#elementId')[0]использования.


Почему $('#elementId')[0]чего-то следует избегать?
Алекс

Я долго отвечал на это, поэтому, используя $ ('# elementId') [0], я думаю, вы всегда указываете, что значение будет в 0-м индексе. Таким образом, вы всегда проверяете 1-й встречающийся элемент. То, что там было несколько флажков с одинаковыми именами, так, вроде радио кнопки. На этот раз длина будет полезна.
Код Buster

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
Почему бы просто, !!если вы хотите логическое значение?
Алекс

Итак, если элемент не имеет идентификатора, то считается, что его нет в 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
Это может привести
Стивен

0

Все существующие элементы имеют установленный parentElement, кроме элемента HTML!

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

Это всегда "HTML" ? Может ли это быть "HTML" ?
Питер Мортенсен

x.tagName или x.nodeName всегда в верхнем регистре, независимо от того, как вы пишете это в своем коде
Иона

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 ).

Примечание. Возвращается значение true, если элемент также добавляется в 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.