Подтвердить что ты не робот

Почему метод jQuery или DOM, такой как getElementById, не находит элемент?

Каковы возможные причины того, что document.getElementById, $("#id") или любой другой селектор метода DOM/jQuery не нашли элементы?

Примеры проблем:

  • JQuery молча не удалось связать обработчик событий
  • jQuery "методы получения" (.val(), .html(), .text()), возвращающие undefined
  • Стандартный метод DOM, возвращающий null, приводящий к любой из нескольких ошибок:

Uncaught TypeError: Невозможно установить свойство '...' для null Uncaught TypeError: Невозможно прочитать свойство '...' с нулевым значением

Наиболее распространенные формы:

Uncaught TypeError: Невозможно установить свойство 'onclick' для null

Uncaught TypeError: Невозможно прочитать свойство 'addEventListener' с нулевым значением

Uncaught TypeError: Невозможно прочитать свойство 'style' из null

4b9b3361

Ответ 1

Элемент, который вы пытались найти, не был в DOM, когда выполнялся ваш script.

Положение вашего DOM-зависимого script может оказать глубокое влияние на его поведение. Браузеры анализируют HTML-документы сверху донизу. Элементы добавляются в DOM, и сценарии выполняются (как правило), когда они встречаются. Это означает, что порядок имеет значение. Обычно сценарии не могут найти элементы, которые появляются позже в разметке, потому что эти элементы еще не добавлены в DOM.

Рассмотрим следующую разметку; script # 1 не удается найти <div>, а script # 2 -

<script>
  console.log("script #1: %o", document.getElementById("test")); // null
</script>
<div id="test">test div</div>
<script>
  console.log("script #2: %o", document.getElementById("test")); // <div id="test" ...
</script>

Ответ 2

Короче и просто:. Поскольку элементы, которые вы ищете, не существуют в документе (пока).


В оставшейся части этого ответа я буду использовать getElementById в качестве примера, но то же самое относится к getElementsByTagName, querySelector и любой другой метод DOM, который выбирает элементы.

Возможные причины

Есть две причины, по которым элемент может не существовать:

Последний случай довольно распространен. Браузеры анализируют и обрабатывают HTML сверху вниз. Это означает, что любой вызов элемента DOM, который происходит до того, как этот элемент DOM появится в HTML, завершится с ошибкой.

Рассмотрим следующий пример:

<script>
    var element = document.getElementById('my_element');
</script>

<div id="my_element"></div>

После script появляется div. В настоящий момент выполняется script, этот элемент еще не существует, а getElementById возвращает null.

JQuery

То же самое относится ко всем селекторам с jQuery. jQuery не найдет элементов, если вы ошибочно написали свой селектор, или вы пытаетесь выбрать их до того, как они действительно существуют.

Добавленный твист - это когда jQuery не найден, потому что вы загрузили script без протокола и запускаетесь из файловой системы:

<script src="//somecdn.somewhere.com/jquery.min.js"></script>

этот синтаксис используется, чтобы позволить script загружать через HTTPS на странице с протоколом https://и загружать версию HTTP на странице с протоколом http://

У этого есть неудачный побочный эффект попытки и невозможность загрузить file://somecdn.somewhere.com...


Решения

Прежде чем делать вызов getElementById (или любого метода DOM, если на то пошло), убедитесь, что существуют элементы, к которым вы хотите получить доступ, т.е. DOM загружен.

Это может быть обеспечено простым помещением вашего JavaScript после соответствующего элемента DOM

<div id="my_element"></div>

<script>
    var element = document.getElementById('my_element');
</script>

и в этом случае вы также можете поместить код непосредственно перед тегом закрывающего тела (</body>) (все элементы DOM будут доступны в момент выполнения script).

Другие решения включают прослушивание load [MDN] или DOMContentLoaded [MDN] события. В этих случаях не имеет значения, где в документе вы размещаете код JavaScript, вам просто нужно запомнить, чтобы весь обработчик DOM обрабатывался в обработчиках событий.

Пример:

window.onload = function() {
    // process DOM elements here
};

// or

// does not work IE 8 and below
document.addEventListener('DOMContentLoaded', function() {
    // process DOM elements here
});

Подробнее о обработке событий и различиях браузера см. в статьях на quirksmode.org.

JQuery

Сначала убедитесь, что jQuery загружен правильно. Используйте инструменты разработчика браузера, чтобы узнать, был ли найден файл jQuery и исправлен ли URL-адрес, если это не так (например, добавьте http: или https: в начале, отрегулируйте путь и т.д.)

Прослушивание событий load/DOMContentLoaded - это именно то, что делает jQuery с .ready() [docs]. Весь ваш код jQuery, который влияет на элемент DOM, должен находиться внутри этого обработчика событий.

Фактически, в учебнике jQuery явно указано:

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

Для этого мы регистрируем готовое событие для документа.

$(document).ready(function() {
   // do stuff when DOM is ready
});

В качестве альтернативы вы также можете использовать сокращенный синтаксис:

$(function() {
    // do stuff when DOM is ready
});

Оба эквивалентны.

Ответ 3

Причины, по которым селекторы на основе id не работают

  • Элемент /DOM с указанным идентификатором еще не существует.
  • Элемент существует, но он не зарегистрирован в DOM [в случае добавления HTML-узлов динамически из ответов Ajax].
  • Присутствует более одного элемента с тем же идентификатором, который вызывает конфликт.

Решения

  • Попробуйте получить доступ к элементу после его объявления или, альтернативно, использовать такие вещи, как $(document).ready();

  • Для элементов, исходящих из ответов Ajax, используйте метод .bind() для jQuery. Более старые версии jQuery имели .live() для того же самого.

  • Используйте инструменты [например, плагин webdeveloper для браузеров], чтобы найти дубликаты идентификаторов и удалить их.

Ответ 4

Как отметил @FelixKling, наиболее вероятным сценарием является то, что узлы, которые вы ищете, пока не существуют.

Однако современные методы разработки часто могут манипулировать элементами документа за пределами дерева документов либо с помощью DocumentFragments, либо просто отделять/повторно присоединять текущие элементы напрямую. Такие методы могут использоваться как часть шаблонов JavaScript или избегать чрезмерных операций перерисовки/переплавки, в то время как элементы, о которых идет речь, сильно изменены.

Аналогично, новая функциональность "Теневой DOM", развернутая в современных браузерах, позволяет элементам быть частью документа, но не может быть выполнена с помощью document.getElementById и всех его методов sibling (querySelector и т.д.). Это делается для инкапсуляции функциональных возможностей и скрыть их.

Опять же, скорее всего, элемент, который вы ищете, просто не является (пока) в документе, и вы должны делать то, что предлагает Феликс. Тем не менее, вы также должны знать, что это все чаще является не единственной причиной того, что элемент может быть неоправданным (временно или постоянно).

Ответ 5

Если элемент, к которому вы пытаетесь получить доступ, находится внутри iframe, и вы пытаетесь получить к нему доступ вне контекста iframe, это также приведет к сбою.

Если вы хотите получить элемент в iframe, вы можете узнать, как здесь.

Ответ 6

Если порядок выполнения сценария не является проблемой, другой возможной причиной проблемы является то, что элемент не выбран должным образом:

  • getElementById требует, чтобы переданная строка была идентификатором дословно, и ничего больше. Если вы передаете переданную строку с #, а идентификатор не начинается с #, ничего не будет выбрано:

    <div id="foo"></div>
    
    // Error, selected element will be null:
    document.getElementById('#foo')
    // Fix:
    document.getElementById('foo')
    
  • Аналогично, для getElementsByClassName не ставьте перед передаваемой строкой .:

    <div class="bar"></div>
    
    // Error, selected element will be undefined:
    document.getElementsByClassName('.bar')[0]
    // Fix:
    document.getElementsByClassName('bar')[0]
    
  • С помощью querySelector, querySelectorAll и jQuery, чтобы сопоставить элемент с определенным именем класса, поместите . непосредственно перед классом. Аналогично, чтобы сопоставить элемент с определенным идентификатором, поместите # непосредственно перед идентификатором:

    <div class="baz"></div>
    
    // Error, selected element will be null:
    document.querySelector('baz')
    $('baz')
    // Fix:
    document.querySelector('.baz')
    $('.baz')
    

    Правила здесь, в большинстве случаев, идентичны правилам для селекторов CSS, и их можно увидеть подробно здесь.

  • Чтобы сопоставить элемент, имеющий два или более атрибута (например, два имени класса или имя класса и атрибут data-), поместите селекторы для каждого атрибута рядом друг с другом в строке селектора, без пробела, разделяющего их (поскольку пробел указывает селектор потомков). Например, чтобы выбрать:

    <div class="foo bar"></div>
    

    используйте строку запроса .foo.bar. Чтобы выбрать

    <div class="foo" data-bar="someData"></div>
    

    используйте строку запроса .foo[data-bar="someData"]. Чтобы выбрать <span> ниже:

    <div class="parent">
      <span data-username="bob"></span>
    </div>
    

    используйте div.parent > span[data-username="bob"].

  • Заглавные буквы и орфография имеют значение для всего вышеперечисленного. Если заглавная буква отличается или орфография отличается, элемент не будет выбран:

    <div class="result"></div>
    
    // Error, selected element will be null:
    document.querySelector('.results')
    $('.Result')
    // Fix:
    document.querySelector('.result')
    $('.result')
    
  • Вы также должны убедиться, что методы имеют правильную прописную букву и орфографию. Используйте одно из:

    $(selector)
    document.querySelector
    document.querySelectorAll
    document.getElementsByClassName
    document.getElementsByTagName
    document.getElementById
    

    Любое другое написание или заглавная буква не будут работать. Например, document.getElementByClassName выдаст ошибку.

  • Убедитесь, что вы передали строку этим методам селектора. Если вы передадите что-то, что не является строкой, querySelector, getElementById и т.д., Это почти наверняка не сработает.

Ответ 7

есть и другая ситуация, которая может вызвать такую ошибку. Представьте, что у вас есть этот код:

<script>
    $(document).ready(function() {
        $('body').append('<div id="my-element"></div>');
    });
</script>

этот код создает элемент #my-element внутри тега body.

и после этого у нас может быть следующий код:

<script>
    console.log($('#my-element'));
</script>

второй код запускается до первого! потому что первый запускается после полной загрузки документа. и это может вызвать ошибку.

Ответ 8

проблема в том, что элемент dom 'speclist' не создается во время выполнения кода javascript. Поэтому я поместил код javascript в функцию и вызвал эту функцию для события onload тела.

function do_this_first(){
   //appending code
}

<body onload="do_this_first()">
</body>

Ответ 9

document.addEventListener("DOMContentLoaded", function () {
    // Handler when the DOM is fully loaded
    const text = document.getElementById("this_text");
    console.log(text.innerHTML)
});

Как мы можем сделать это с помощью ванильного JavaScript. Нет необходимости JQuery.

Ответ 10

Я просто боролся с этим и делился, если это было полезно.

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

В конце я переписал строку кода. Я не ошиблись, но думаю, что я использовал буквы "ID". Теперь он отлично работает.

Ответ 11

Попробуйте поместить document.getElementById в setTimeout()

Например

setTimeout(function(){
    console.log(document.getElementById('whatever'));
}, 100);

Если это сработает, тогда это просто проблема времени.