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.

morocklo
źródło
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);
}
Rob M.
źródło
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>");
}
Dilip Agheda
źródło
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.

sridhar
źródło
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.

MattSidor
źródło
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.

Ajit Kumar
źródło
8

skrypt ładuje się przed treścią, zachowaj skrypt po treści

Sagar M
źródło
5

Umieść skrypt na końcu tagu body.

<html>
    <body>
        .........
        <script src="main.js"></script>
    </body>
</html>
matak8s
źródło
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;
  };
}
morocklo
źródło
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

Andy Smith
źródło
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.

Mahmud
źródło
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()" ....>
    .....
pjm
źródło
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);
  })

})
Ambreen Fatima
źródło
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.

Baseer Ebadi
źródło
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.

ultrageek
źródło
-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.

Xcode
źródło
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(){}
Natalie Jimenez
źródło
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