Неможливо прочитати властивість 'addEventListener' з null


106

Я повинен використовувати ванільний JavaScript для проекту. У мене є кілька функцій, одна з яких - кнопка, яка відкриває меню. Він працює на сторінках, де існує цільовий ідентифікатор, але викликає помилку на сторінках, де ідентифікатор не існує. На тих сторінках, де функція не може знайти ідентифікатор, я отримую помилку "Неможливо прочитати властивість" addEventListener "з нулем", і жодна з інших моїх функцій не працює.

Нижче - код кнопки, яка відкриває меню.

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 "з нулем", і жодна з інших моїх функцій не працює. Я думаю, що відповідь була майже у питанні. Ви не змогли знайти елемент, тому не можете додати до нього слухача події ...
Etai

1
Це може просто статися, якщо ви classзамість цього використовували ваш html idта ви закликали до getElementByIdсвого сценарію.
Дек

Відповіді:


198

Я думаю, що найпростішим підходом було б просто перевірити, elчи не є нульовим, перш ніж додати слухача подій:

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

приголомшливий це зробило трюк. Я також перемістив функцію onclick в оператор if, якщо. Кінцевий код я розмістив нижче.
morocklo

3
це буде nullперед тим, як реагувати компонент змонтується!

Людина подяки: D Саме те, що я шукав .... У моєму додатку є кілька слухачів, і слухачі розкидані по-різному. Якщо елемент присутній на сторінці, він
вимальовував

Так корисно, дякую!
sc_props

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

Це просто, що ваш JS завантажується перед HTML-частиною, тому він не може знайти цей елемент. Просто покладіть весь код JS всередину функції, яка буде викликана, коли вікно завантажується.

Ви також можете помістити свій код Javascript під HTML.


8

сценарій завантажується перед body, зберігати сценарій після вмісту


5

Покладіть скрипт в кінець тегу тіла.

<html>
    <body>
        .........
        <script src="main.js"></script>
    </body>
</html>

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 дозволяє нам записувати асинхронний код синхронно. це просто синтаксичний цукор, використовуючи генератори та заяви про вихід, щоб "призупинити" виконання, даючи нам можливість призначити його змінній!

Ось посилання на посилання- https://medium.com/siliconwat/how-javascript-async-await-works-3cab4b7d21da


2

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


0

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

Але мені не подобається рішення про упорядкування вмісту.

Краще рішення - помістити обробник подій на сторінку події завантаження і встановити слухача туди. Це забезпечить завантаження сторінки та цільового елемента перед виконанням завдання. напр

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

    <body onload="onLoadFunct()" ....>
    .....

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 функцією init (називайте його, що ви хочете). Це спрацювало, тому, принаймні в моєму випадку, я додав слухача події до завантаження документа. Це може бути і те, що ви переживаєте.


-1

Це тому, що елемент не завантажувався в той час, коли виконувався пакет js.

Я переміщу <script src="sample.js" type="text/javascript"></script>би на саму нижню частину index.htmlфайлу. Таким чином ви можете переконатися, що сценарій виконується після того, як всі елементи html були проаналізовані та надані.


Неправильно. Це старе шкільне мислення. Завантаження в кінці затримує завантаження, як ви заявили, але це не забезпечує отримання домену повністю . У мене були старші сторінки, які використовували цей злом, не запускалися, оскільки малюнок 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 буде повністю намальований.
Machavity

Дякую, я спробую. Я отримав свою відповідь від мережі Mozilla. Я подумав, що це довірливе джерело.
Наталі Хіменес
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.