Каковы возможные причины того document.getElementById
, что $("#id")
любой другой селектор метода DOM / jQuery не находит элементы?
Примеры проблем включают в себя:
- JQuery молча не удается связать обработчик событий
- JQuery "геттерные" методы (
.val()
,.html()
,.text()
) возвращениеundefined
- Стандартный метод DOM, возвращающий в
null
результате любую из нескольких ошибок:
Uncaught TypeError: Невозможно установить свойство '...' с нулевым значением Uncaught TypeError: Невозможно прочитать свойство '...' с нулевым значением
Наиболее распространенные формы:
Uncaught TypeError: Невозможно установить свойство 'onclick' для null
Uncaught TypeError: Невозможно прочитать свойство 'addEventListener' с нулевым значением
Uncaught TypeError: Невозможно прочитать свойство 'style' из null
javascript
jquery
dom
Феликс Клинг
источник
источник
Ответы:
Элемент, который вы пытались найти, отсутствовал в DOM, когда выполнялся ваш скрипт.
Положение вашего DOM-зависимого скрипта может сильно повлиять на его поведение. Браузеры анализируют HTML-документы сверху вниз. Элементы добавляются в DOM, и сценарии (как правило) выполняются по мере их появления. Это означает, что порядок имеет значение. Как правило, сценарии не могут найти элементы, которые появляются позже в разметке, потому что эти элементы еще не добавлены в DOM.
Рассмотрим следующую разметку; сценарий № 1 не может найти,
<div>
а сценарий № 2 завершается успешно:Итак, что нужно сделать? У вас есть несколько вариантов:
Вариант 1. Переместите ваш скрипт
Переместите ваш скрипт дальше вниз по странице, непосредственно перед закрывающим тегом body. Организованный таким образом, остальная часть документа анализируется перед выполнением вашего скрипта:
Примечание. Размещение сценариев внизу обычно считается лучшей практикой .
Вариант 2: JQuery's
ready()
Отложите ваш скрипт, пока DOM не будет полностью проанализирован, используя :
$(handler)
Примечание: вы можете просто привязать
DOMContentLoaded
или, но у каждого есть свои предостережения. JQuery предлагает гибридное решение.window.onload
ready()
Вариант 3: делегирование событий
Когда элемент вызывает событие (при условии, что это пузырьковое событие, и ничто не останавливает его распространение), каждый родительский элемент в происхождении этого элемента также получает событие. Это позволяет нам присоединять обработчик к существующему элементу и сэмплировать события, когда они всплывают от его потомков ... даже тех, которые добавлены после присоединения обработчика. Все, что нам нужно сделать, это проверить событие, чтобы увидеть, было ли оно вызвано нужным элементом, и, если это так, запустить наш код.
JQuery's
on()
выполняет эту логику для нас. Мы просто предоставляем имя события, селектор для желаемого потомка и обработчик события:Примечание: как правило, этот шаблон зарезервирован для элементов, которые не существовали во время загрузки или чтобы избежать подключения большого количества обработчиков. Стоит также отметить, что, хотя я и прикрепил обработчик
document
(для демонстрационных целей), вы должны выбрать ближайшего надежного предка.Вариант 4:
defer
атрибутИспользуйте
defer
атрибут<script>
.Для справки вот код из этого внешнего скрипта :
Примечание:
defer
атрибут, безусловно, выглядит как волшебная палочка, но важно знать о предостережениях ...1.
defer
может использоваться только для внешних сценариев, то есть для тех, которые имеютsrc
атрибут.2. знать о поддержке браузера , то есть: ошибочная реализация в IE <10
источник
<head>
и использую ихdefer
(мне не нужно поддерживать старые, несовместимые браузеры)defer
и другиеasync
имеют довольно широкую поддержку - даже если вернуться к некоторым более старым версиям браузера. У них есть дополнительное преимущество: они четко и явно сигнализируют о предполагаемом поведении. Просто помните, что эти атрибуты работают только для сценариев, указывающихsrc
атрибут, то есть для внешних сценариев. Взвесьте преимущества. Может использовать оба? Ваш звонок.Коротко и просто: потому что искомые элементы не существуют в документе (пока).
В течение оставшейся части этого ответа я буду использовать в
getElementById
качестве примера, но то же самое относится и кgetElementsByTagName
,querySelector
и любой другой метод , который выбирает DOM - элементов.Возможные причины
Есть две причины, почему элемент может не существовать:
Элемент с переданным идентификатором действительно не существует в документе. Вы должны дважды проверить, что идентификатор, который вы передаете,
getElementById
действительно совпадает с идентификатором существующего элемента в (сгенерированном) HTML, и что вы не ошиблись идентификатором (идентификаторы чувствительны к регистру !).Между прочим, в большинстве современных браузеров , которые реализуют
querySelector()
иquerySelectorAll()
методы, нотация в стиле CSS используется для извлечения элемента егоid
, например:document.querySelector('#elementID')
в отличие от метода, которым элемент извлекается егоid
underdocument.getElementById('elementID')
; в первом#
символ важен, во втором - элемент не будет извлечен.Элемент не существует в тот момент, когда вы звоните
getElementById
.Последний случай довольно распространен. Браузеры анализируют и обрабатывают HTML сверху вниз. Это означает, что любой вызов элемента DOM, который происходит до того, как этот элемент DOM появится в HTML, не будет выполнен.
Рассмотрим следующий пример:
div
Появляется послеscript
. На данный момент скрипт выполняется, то элемент не существует еще иgetElementById
вернетсяnull
.JQuery
То же самое относится ко всем селекторам с jQuery. jQuery не найдет элементы, если вы неправильно написали свой селектор или пытаетесь выбрать их до того, как они реально появятся .
Добавленный поворот - это когда jQuery не найден, потому что вы загрузили скрипт без протокола и работаете из файловой системы:
этот синтаксис позволяет скрипту загружаться через HTTPS на страницу с протоколом https: // и загружать версию HTTP на страницу с протоколом http: //
Это имеет неприятный побочный эффект попытки и не удается загрузить
file://somecdn.somewhere.com...
Решения
Перед тем, как сделать вызов
getElementById
(или любой другой метод DOM), убедитесь, что элементы, к которым вы хотите получить доступ, существуют, то есть загружен DOM.Это можно сделать, просто поместив свой JavaScript после соответствующего элемента DOM
в этом случае вы также можете поместить код непосредственно перед закрывающим тегом body (
</body>
) (все элементы DOM будут доступны во время выполнения скрипта).Другие решения включают прослушивание событий
load
[MDN] илиDOMContentLoaded
[MDN] . В этих случаях не имеет значения, где в документе вы размещаете код JavaScript, вы просто должны помнить, чтобы поместить весь код обработки DOM в обработчики событий.Пример:
Пожалуйста, смотрите статьи на quirksmode.org для получения дополнительной информации об обработке событий и различиях браузера.
JQuery
Сначала убедитесь, что jQuery загружен правильно. Используйте инструменты разработчика браузера, чтобы узнать, был ли найден файл jQuery, и исправьте URL-адрес, если его нет (например, добавьте схему
http:
илиhttps:
в начале, измените путь и т. Д.)Прослушивание событий
load
/DOMContentLoaded
- это именно то, что делает jQuery с.ready()
[docs] . Весь ваш код jQuery, который влияет на элемент DOM, должен быть внутри этого обработчика событий.На самом деле, учебник по jQuery прямо заявляет:
В качестве альтернативы вы также можете использовать сокращенный синтаксис:
Оба эквивалентны.
источник
ready
событие, чтобы отразить «более новый» предпочтительный синтаксис, или лучше оставить его как есть, чтобы оно работало в более старых версиях?$(window).load()
(и , возможно , синтаксических альтернатив$(document).ready()
,$(function(){})
это , кажется , связаны, но это? Чувствует немного по касательной к точке вы делаете..load
. Что касается синтаксических альтернатив, их можно найти в документации, но поскольку ответы должны быть самодостаточными, возможно, их стоит добавить. Опять же, я почти уверен, что на этот конкретный бит о jQuery уже дан ответ, и, вероятно, он описан в других ответах, и ссылки на него могут быть достаточными..load
не рекомендуется: api.jquery.com/load-event . Я не знаю, только для изображений илиwindow
так же.Причины, по которым селекторы на основе идентификаторов не работают
Решения
Попробуйте получить доступ к элементу после его объявления или, в качестве альтернативы, использовать такие вещи, как
$(document).ready();
Для элементов, полученных из ответов Ajax, используйте
.bind()
метод jQuery. Более старые версии jQuery были.live()
для того же.Используйте инструменты [например, плагин веб-разработчика для браузеров], чтобы найти дубликаты идентификаторов и удалить их.
источник
Как отметил @FelixKling, наиболее вероятный сценарий - то, что искомые узлы не существуют (пока).
Однако современные методы разработки часто могут манипулировать элементами документа за пределами дерева документа либо с помощью DocumentFragments, либо просто напрямую отсоединяя / присоединяя текущие элементы. Такие методы могут использоваться как часть шаблонов JavaScript или чтобы избежать чрезмерных операций перерисовки / перекомпоновки, когда рассматриваемые элементы сильно изменяются.
Точно так же новая функциональность «Shadow DOM», внедряемая в современных браузерах, позволяет элементам быть частью документа, но не способным выполнять запросы с помощью document.getElementById и всех его родственных методов (querySelector и т. Д.). Это сделано для инкапсуляции функциональности и, в частности, ее скрытия.
Опять же, тем не менее, наиболее вероятно, что искомого элемента просто нет (пока) в документе, и вам следует поступить так, как предлагает Феликс. Тем не менее, вы также должны знать, что это не единственная причина, по которой элемент может быть невозможно найти (временно или навсегда).
источник
Если элемент, к которому вы пытаетесь получить доступ, находится внутри,
iframe
и вы пытаетесь получить к нему доступ вне контекста,iframe
это также приведет к его отказу.Если вы хотите получить элемент в iframe, вы можете узнать, как здесь .
источник
Если порядок выполнения скрипта не является проблемой, другой возможной причиной проблемы является то, что элемент выбран неправильно:
getElementById
требует, чтобы переданная строка была идентификатором дословно , и ничего больше. Если вы передаете переданную строку с a#
, а идентификатор не начинается с a#
, ничего не будет выбрано:Точно так же, для
getElementsByClassName
, не используйте префикс переданной строки с.
:С помощью querySelector, querySelectorAll и jQuery, чтобы сопоставить элемент с определенным именем класса, поместите
.
непосредственно перед классом. Аналогично, чтобы сопоставить элемент с определенным идентификатором, поместите#
непосредственно перед идентификатором:Правила здесь, в большинстве случаев, идентичны правилам для селекторов CSS, и их можно подробно увидеть здесь .
Чтобы сопоставить элемент, имеющий два или более атрибута (например, два имени класса или имя класса и
data-
атрибут), поместите селекторы для каждого атрибута рядом друг с другом в строке селектора, без пробела, разделяющего их (поскольку пробел указывает селектор потомок ). Например, чтобы выбрать:используйте строку запроса
.foo.bar
. Выбиратьиспользуйте строку запроса
.foo[data-bar="someData"]
. Чтобы выбрать<span>
ниже:использовать
div.parent > span[data-username="bob"]
.Капитализация и орфография имеет значение для всего вышеперечисленного. Если заглавная буква отличается или орфография отличается, элемент не будет выбран:
Вы также должны убедиться, что методы имеют правильную прописную букву и орфографию. Используйте один из:
Любое другое написание или заглавные буквы не будут работать. Например,
document.getElementByClassName
выдаст ошибку.Убедитесь, что вы передали строку этим методам селектора. Если вы передаете то , что не является строка
querySelector
,getElementById
и т.д., это почти наверняка не будет работать.источник
Когда я попробовал твой код, он работал.
Единственная причина, по которой ваше событие не работает, может заключаться в том, что ваш DOM не был готов, а ваша кнопка с идентификатором "event-btn" еще не была готова. И ваш javascript был выполнен и попытался связать событие с этим элементом.
Перед использованием элемента DOM для привязки этот элемент должен быть готов. Есть много вариантов сделать это.
Вариант 1. Вы можете переместить свой код привязки события в событие готовности документа. Подобно:
Вариант 2. Вы можете использовать событие тайм-аута, чтобы привязка задерживалась на несколько секунд. подобно:
Вариант 3: переместите ваш Javascript включить в нижней части вашей страницы.
Я надеюсь, это поможет вам.
источник
проблема в том, что элемент dom 'speclist' не создается во время выполнения кода javascript. Поэтому я поместил код javascript в функцию и вызвал эту функцию для события onload тела.
источник
Мое решение было не использовать идентификатор элемента якоря:
<a id='star_wars'>Place to jump to</a>
. По-видимому, у блейзоров и других фреймворков спа есть проблемы с переходом на якоря на той же странице. Чтобы обойти это я должен был использоватьdocument.getElementById('star_wars')
. Однако это не сработало , пока я не поставил идентификатор в элементе абзаца вместо:<p id='star_wars'>Some paragraph<p>
.Пример использования начальной загрузки:
источник