Невозможно прочитать свойство addEventListener со значением null

108

Мне нужно использовать ванильный JavaScript для проекта. У меня есть несколько функций, одна из которых - кнопка, открывающая меню. Он работает на страницах, где существует целевой идентификатор, но вызывает ошибку на страницах, где идентификатор не существует. На тех страницах, где функция не может найти идентификатор, я получаю сообщение об ошибке «Не удается прочитать свойство addEventListener 'со значением null», и ни одна из других моих функций не работает.

Ниже приведен код кнопки, открывающей меню.

function swapper() {
toggleClass(document.getElementById('overlay'), 'open');
}

var el = document.getElementById('overlayBtn');
el.addEventListener('click', swapper, false);

var text = document.getElementById('overlayBtn');
text.onclick = function(){
this.innerHTML = (this.innerHTML === "Menu") ? "Close" : "Menu";
return false;
};

Как мне с этим справиться? Мне, вероятно, нужно обернуть этот код другой функцией или использовать оператор if / else, чтобы он выполнял поиск только идентификатора на определенных страницах, но не был уверен в точности.

морокло
источник
1
Вы можете показать код HTML. похоже, что не может найти элемент с id 'overlayBtn'
BlaShadow
2
На тех страницах, где функция не может найти идентификатор, я получаю сообщение об ошибке «Не удается прочитать свойство addEventListener 'со значением null», и ни одна из других моих функций не работает. Думаю, ответ заключался в самом вопросе. Вы не смогли найти элемент, поэтому вы не можете добавить к нему прослушиватель событий ...
Etai,
1
Это может просто случиться, если вы использовали classв своем html вместо idи вызываете a getElementByIdв своих скриптах.
Deke
Просто столкнулся с аналогичной проблемой где addEventListener could be null. Перемещение <script src="..."></script>после <body/>тега, похоже, решает эту проблему.
Reborn

Ответы:

202

Я думаю, что самым простым подходом было бы просто проверить, elне является ли значение null перед добавлением прослушивателя событий:

var el = document.getElementById('overlayBtn');
if(el){
  el.addEventListener('click', swapper, false);
}
Роб М.
источник
здорово. это сработало. Я также переместил функцию onclick в этот оператор if. Я разместил окончательный код ниже.
morocklo
3
это будет nullдо того, как будет смонтирован реагирующий компонент!
Спасибо, чувак: D Именно то, что я искал .... У меня есть несколько слушателей в моем приложении, и слушатели распределены в разных представлениях. Если элемент присутствует на странице, он испортил мой JS
VegaStudios
113

Кажется, что document.getElementById('overlayBtn');он возвращается, nullпотому что он выполняется до полной загрузки DOM.

Если вы поместите эту строку кода в

window.onload=function(){
  -- put your code here
}

тогда он будет работать без проблем.

Пример:

window.onload=function(){
    var mb = document.getElementById("b");
    mb.addEventListener("click", handler);
    mb.addEventListener("click", handler2);
}


function handler() {
    $("p").html("<br>" + $("p").text() + "<br>You clicked me-1!<br>");
}

function handler2() {
    $("p").html("<br>" + $("p").text() + "<br>You clicked me-2!<br>");
}
Дилип Агеда
источник
23

Я столкнулся с похожей ситуацией. Вероятно, это связано с тем, что сценарий выполняется до загрузки страницы. Поместив скрипт внизу страницы, я обошел проблему.

Шридхар
источник
1
Да, я думаю, что есть несколько решений этой проблемы в зависимости от сценария.
rpeg
16

Я получал ту же ошибку, но выполнение нулевой проверки не помогло.

Решение, которое я нашел, заключалось в том, чтобы заключить мою функцию в прослушиватель событий для всего документа, чтобы проверить, когда DOM завершит загрузку.

document.addEventListener('DOMContentLoaded', function () {
    el.addEventListener('click', swapper, false);
});

Я думаю, это потому, что я использую фреймворк (Angular), который динамически меняет мои классы HTML и идентификаторы.

МэттСидор
источник
1
Я сталкиваюсь с той же проблемой при игре с Electron. Сохранил тем же способом.
Чарльз
9

Это просто bcz, ваш JS загружается до HTML-части, поэтому он не может найти этот элемент. Просто поместите весь свой JS-код в функцию, которая будет вызываться при загрузке окна.

Вы также можете поместить свой код Javascript под html.

Аджит Кумар
источник
8

сценарий загружается до тела, сохранить сценарий после содержимого

Сагар М
источник
6

Поместите скрипт в конец тега body.

<html>
    <body>
        .........
        <script src="main.js"></script>
    </body>
</html>
matak8s
источник
3

Спасибо @Rob M. за его помощь. Вот как выглядел последний блок кода:

function swapper() {
  toggleClass(document.getElementById('overlay'), 'open');
}

var el = document.getElementById('overlayBtn');
if (el){
  el.addEventListener('click', swapper, false);

  var text = document.getElementById('overlayBtn');
  text.onclick = function(){
    this.innerHTML = (this.innerHTML === "Menu") ? "Close" : "Menu";
    return false;
  };
}
морокло
источник
2

Я просто добавил «async» в свой тег скрипта, который, похоже, устранил проблему. Я не уверен, почему, если кто-то может объяснить, но у меня это сработало. Я предполагаю, что страница не ждет загрузки скрипта, поэтому страница загружается одновременно с JavaScript.

Async / Await позволяет нам писать асинхронный код в синхронном режиме. это просто синтаксический сахар, использующий генераторы и операторы yield для «приостановки» выполнения, что дает нам возможность назначить его переменной!

Вот справочная ссылка - https://medium.com/siliconwat/how-javascript-async-await-works-3cab4b7d21da

Энди Смит
источник
2

Я столкнулся с той же проблемой и проверил значение null, но это не помогло. Потому что скрипт загружался до загрузки страницы. Таким образом, простое размещение скрипта перед конечным тегом тела решило проблему.

Махмуд
источник
0

Как говорили другие, проблема в том, что скрипт выполняется до загрузки страницы (и, в частности, целевого элемента).

Но мне не нравится решение переупорядочить контент.

Предпочтительное решение - поместить обработчик событий в событие загрузки страницы и установить там Listener. Это обеспечит загрузку страницы и целевого элемента до выполнения назначения. например

    <script>
    function onLoadFunct(){
            // set Listener here, also using suggested test for null
    }
    ....
    </script>

    <body onload="onLoadFunct()" ....>
    .....
pjm
источник
0

У меня есть коллекция цитат с именами. Я использую кнопку обновления, чтобы обновить последнюю цитату, связанную с определенным именем, но при нажатии кнопки обновления она не обновляется. Я включаю код ниже для файла server.js и внешнего файла js (main.js).

main.js (внешний js)

var update = document.getElementById('update');
if (update){
update.addEventListener('click', function () {

  fetch('quotes', {
  method: 'put',
  headers: {'Content-Type': 'application/json'},
  body: JSON.stringify({
    'name': 'Muskan',
    'quote': 'I find your lack of faith disturbing.'
  })
})var update = document.getElementById('update');
if (update){
update.addEventListener('click', function () {

  fetch('quotes', {
  method: 'put',
  headers: {'Content-Type': 'application/json'},
  body: JSON.stringify({
    'name': 'Muskan',
    'quote': 'I find your lack of faith disturbing.'
  })
})
.then(res =>{
    if(res.ok) return res.json()
})
.then(data =>{
    console.log(data);
    window.location.reload(true);
})
})
}

файл server.js

app.put('/quotes', (req, res) => {
  db.collection('quotations').findOneAndUpdate({name: 'Vikas'},{
    $set:{
        name: req.body.name,
        quote: req.body.quote
    }
  },{
    sort: {_id: -1},
    upsert: true
  },(err, result) =>{
    if (err) return res.send(err);
    res.send(result);
  })

})
Амбрин Фатима
источник
0

Спасибо всем, загружайте скрипты на определенных страницах, которые вы используете, а не на всех страницах, иногда используя swiper.js или другую библиотеку, это может вызвать это сообщение об ошибке, единственный способ решить эту проблему - загрузить библиотеку JS на определенных страницах этот идентификатор существует и предотвращает загрузку одной и той же библиотеки на всех страницах.

Надеюсь, это поможет вам.

Басир Эбади
источник
0

У меня была такая же проблема, но присутствовал мой идентификатор. Поэтому я попытался добавить "window.onload = init;" Затем я обернул свой исходный код JS функцией инициализации (называйте ее как хотите). Это сработало, поэтому, по крайней мере, в моем случае я добавлял прослушиватель событий до загрузки моего документа. Это может быть то, что вы тоже испытываете.

ультрагик
источник
-1

Это связано с тем, что элемент не был загружен в то время, когда выполнялся пакет js.

Я бы переместил в <script src="sample.js" type="text/javascript"></script>самый конец index.htmlфайла. Таким образом, вы можете гарантировать выполнение скрипта после того, как все элементы html были проанализированы и отрисованы.

Xcode
источник
Неправильно. Это старая школа мышления. Загрузка в конце задерживает загрузку, как вы заявили, но не гарантирует, что DOM будет полностью отрисован . У меня были старые страницы, которые использовали этот хак, не запускались, потому что отрисовка DOM была медленнее, чем загрузка. Этот ответ гарантирует, что DOM будет нарисован перед выполнением.
Machavity
-3

Добавляйте все прослушиватели событий при загрузке окна. Работает как шарм независимо от того, куда вы помещаете теги скрипта.

window.addEventListener("load", startup);

function startup() {

  document.getElementById("el").addEventListener("click", myFunc);
  document.getElementById("el2").addEventListener("input", myFunc);

}

myFunc(){}
Натали Хименес
источник
Рисование страницы иногда может занимать больше времени, чем загрузка скрипта, поэтому положение не так важно во всех случаях. Добавление слушателя является предпочтительным способом, но loadтакже не рекомендуется по той же причине. DOMContentLoaded - предпочтительный способ, поскольку он запускается только после того, как DOM полностью отрисован.
Мачавити
Спасибо, я постараюсь. Я получил ответ из сети Mozilla. Я думал, что это надежный источник.
Натали Хименес