Nie można odczytać właściwości „addEventListener” o wartości null


106

Muszę użyć waniliowego JavaScript do projektu. Mam kilka funkcji, z których jedną jest przycisk otwierający menu. Działa na stronach, na których istnieje identyfikator docelowy, ale powoduje błąd na stronach, na których identyfikator nie istnieje. Na tych stronach, na których funkcja nie może znaleźć identyfikatora, pojawia się błąd „Nie można odczytać właściwości 'addEventListener' o wartości null” i żadna z moich innych funkcji nie działa.

Poniżej znajduje się kod przycisku otwierającego menu.

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;
};

Jak sobie z tym radzę? Prawdopodobnie muszę zawinąć ten kod w inną funkcję lub użyć instrukcji if / else, tak aby szukał identyfikatora tylko na określonych stronach, ale nie był pewien dokładnie.


1
czy możesz pokazać kod html. wygląda na to, że nie można znaleźć elementu o identyfikatorze „overlayBtn”
BlaShadow

2
Na tych stronach, na których funkcja nie może znaleźć identyfikatora, pojawia się błąd „Nie można odczytać właściwości 'addEventListener' o wartości null” i żadna z moich innych funkcji nie działa. Myślę, że odpowiedź była w dużej mierze w pytaniu. Nie mogłeś znaleźć elementu, więc nie możesz dodać do niego detektora zdarzenia ...
Etai

1
Może się to po prostu zdarzyć, jeśli użyłeś classw swoim html zamiast idi wzywasz getElementByIdw swoich skryptach.
Deke

Odpowiedzi:


198

Myślę, że najłatwiejszym podejściem byłoby po prostu sprawdzenie, elczy nie jest zerowe, przed dodaniem detektora zdarzeń:

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

niesamowite. to załatwiło sprawę. Przeniosłem również funkcję onclick do tej instrukcji if. Ostateczny kod zamieściłem poniżej.
morocklo,

3
będzie nullprzed zamontowaniem elementu reagującego!

Dzięki człowiekowi: D Dokładnie to, czego szukałem ... Mam wielu słuchaczy w mojej aplikacji, a słuchacze są rozproszeni w różnych poglądach. Jeśli element jest obecny na stronie, to
zepsuł

Tak przydatne, dzięki!
sc_props

113

Wygląda na document.getElementById('overlayBtn');to, że powraca, nullponieważ jest wykonywany przed pełnym załadowaniem DOM.

Jeśli umieścisz tę linię kodu pod

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

wtedy będzie działać bez problemu.

Przykład:

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

Miałem podobną sytuację. Dzieje się tak prawdopodobnie dlatego, że skrypt jest wykonywany przed załadowaniem strony. Umieszczając skrypt na dole strony, ominąłem problem.


1
Tak, myślę, że istnieje wiele rozwiązań tego problemu w zależności od scenariusza.
rpeg

16

Otrzymałem ten sam błąd, ale sprawdzenie zerowej wartości nie pomogło.

Rozwiązaniem, które znalazłem, było umieszczenie mojej funkcji w detektorze zdarzeń, aby cały dokument sprawdzał, kiedy zakończy się ładowanie DOM.

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

Myślę, że dzieje się tak, ponieważ używam frameworka (angular), który dynamicznie zmienia moje klasy HTML i identyfikatory.


1
Napotykam ten sam problem podczas gry z Electronem. Zapisałem go tą samą metodą.
Karol

9

Po prostu bcz twój JS zostanie załadowany przed częścią HTML, więc nie może znaleźć tego elementu. Po prostu umieść cały kod JS w funkcji, która zostanie wywołana po załadowaniu okna.

Możesz także umieścić swój kod JavaScript poniżej html.



5

Umieść skrypt na końcu tagu body.

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

3

Dzięki @Rob M. za jego pomoc. Tak wyglądał ostatni blok kodu:

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

Po prostu dodałem „async” do mojego tagu skryptu, co prawdopodobnie rozwiązało problem. Nie jestem pewien dlaczego, jeśli ktoś może wyjaśnić, ale to zadziałało. Domyślam się, że strona nie czeka na załadowanie skryptu, więc strona ładuje się w tym samym czasie, co JavaScript.

Async / Await umożliwia nam pisanie kodu asynchronicznego w sposób synchroniczny. to po prostu cukier składniowy używający generatorów i instrukcji yield do „wstrzymania” wykonywania, co daje nam możliwość przypisania go do zmiennej!

Oto link referencyjny - https://medium.com/siliconwat/how-javascript-async-await-works-3cab4b7d21da


2

Napotkałem ten sam problem i sprawdziłem, czy nie ma wartości null, ale to nie pomogło. Ponieważ skrypt ładował się przed załadowaniem strony. Zatem samo umieszczenie skryptu przed tagiem end body rozwiązało problem.


0

Jak powiedzieli inni, problem polega na tym, że skrypt jest wykonywany przed załadowaniem strony (aw szczególności elementu docelowego).

Ale nie podoba mi się rozwiązanie polegające na zmianie kolejności treści.

Preferowanym rozwiązaniem jest umieszczenie modułu obsługi zdarzeń na zdarzeniu onload strony i ustawienie tam detektora. Zapewni to załadowanie strony i elementu docelowego przed wykonaniem przypisania. na przykład

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

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

0

Mam zbiór cytatów wraz z nazwiskami. Używam przycisku aktualizacji, aby zaktualizować ostatnią wycenę powiązaną z określoną nazwą, ale po kliknięciu przycisku aktualizacji nie aktualizuje się. Dołączam kod poniżej dla pliku server.js i zewnętrznego pliku js (main.js).

main.js (zewnętrzny 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);
})
})
}

plik 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

Dziękuję wszystkim, Załaduj skrypty na określonych stronach, których używasz, nie dla wszystkich stron, czasami używając swiper.js lub innej biblioteki może to spowodować ten komunikat o błędzie, jedynym sposobem rozwiązania tego problemu jest załadowanie biblioteki JS na określonych stronach ten identyfikator istnieje i zapobiega ładowaniu tej samej biblioteki na wszystkich stronach.

Mam nadzieję, że to ci pomoże.


0

Miałem ten sam problem, ale mój identyfikator był obecny. Więc próbowałem dodać "window.onload = init;" Następnie opakowałem mój oryginalny kod JS funkcją init (nazwij to, jak chcesz). To zadziałało, więc przynajmniej w moim przypadku dodawałem detektor zdarzeń przed załadowaniem mojego dokumentu. To może być również to, czego doświadczasz.


-1

Dzieje się tak, ponieważ element nie został załadowany w czasie wykonywania pakietu js.

Przeniósłbym <script src="sample.js" type="text/javascript"></script>na sam dół index.htmlpliku. W ten sposób możesz zapewnić wykonanie skryptu po przeanalizowaniu i wyrenderowaniu wszystkich elementów HTML.


Błędny. To jest myślenie starej szkoły. Ładowanie na końcu opóźnia ładowanie, jak powiedziałeś, ale nie zapewnia pełnego narysowania DOM . Nie udało mi się uruchomić starszych stron, które korzystały z tego hacka, ponieważ rysowanie DOM było wolniejsze niż ładowanie. Ta odpowiedź zapewnia, że DOM jest rysowany przed wykonaniem.
Machavity

-3

Dodawaj wszystkie detektory zdarzeń, gdy okno się ładuje. Działa jak urok bez względu na to, gdzie umieścisz tagi skryptu.

window.addEventListener("load", startup);

function startup() {

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

}

myFunc(){}

Rysowanie strony może czasami zająć więcej czasu niż ładowanie skryptu, więc pozycja nie jest tak ważna we wszystkich przypadkach. Dodanie odbiornika jest preferowanym sposobem, ale loadjest również przestarzałe z tego samego powodu. DOMContentLoaded jest preferowanym sposobem, ponieważ uruchamia się dopiero po całkowitym narysowaniu DOM.
Machavity

Dzięki spróbuję. Otrzymałem odpowiedź z sieci Mozilla. Myślałem, że to ufne źródło.
Natalie Jimenez
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.