Die Eigenschaft 'addEventListener' von null kann nicht gelesen werden

105

Ich muss Vanille-JavaScript für ein Projekt verwenden. Ich habe einige Funktionen, von denen eine eine Schaltfläche ist, die ein Menü öffnet. Es funktioniert auf Seiten, auf denen die Ziel-ID vorhanden ist, verursacht jedoch einen Fehler auf Seiten, auf denen die ID nicht vorhanden ist. Auf den Seiten, auf denen die Funktion die ID nicht finden kann, wird der Fehler "Eigenschaft 'addEventListener' von null kann nicht gelesen werden" angezeigt, und keine meiner anderen Funktionen funktioniert.

Unten finden Sie den Code für die Schaltfläche, mit der das Menü geöffnet wird.

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

Wie gehe ich damit um? Ich muss diesen Code wahrscheinlich alle in eine andere Funktion einschließen oder eine if / else-Anweisung verwenden, damit nur auf bestimmten Seiten nach der ID gesucht wird, aber nicht genau.

Morocklo
quelle
1
Können Sie den HTML-Code anzeigen? es scheint, dass kein Element mit der ID 'overlayBtn' gefunden werden kann
BlaShadow
2
Auf den Seiten, auf denen die Funktion die ID nicht finden kann, wird der Fehler "Eigenschaft 'addEventListener' von null kann nicht gelesen werden" angezeigt, und keine meiner anderen Funktionen funktioniert. Ich denke, die Antwort war so ziemlich in der Frage. Sie konnten das Element nicht finden, also können Sie ihm keinen Ereignis-Listener hinzufügen ...
Etai
1
Es kann einfach passieren, wenn Sie classin Ihrem HTML statt verwendet haben idund Sie getElementByIdin Ihren Skripten ein fordern .
Deke

Antworten:

196

Ich denke, der einfachste Ansatz wäre, elvor dem Hinzufügen eines Ereignis-Listeners zu überprüfen, ob er nicht null ist:

var el = document.getElementById('overlayBtn');
if(el){
  el.addEventListener('click', swapper, false);
}
Rob M.
quelle
genial. Das hat funktioniert. Ich habe auch die onclick-Funktion in diese if-Anweisung verschoben. Ich habe den endgültigen Code unten gepostet.
Morocklo
3
Es wird sein, nullbevor die Reaktionskomponente montiert wurde!
Danke Mann: D Genau das, wonach ich gesucht habe ... Ich habe mehrere Hörer in meiner App und die Hörer sind in verschiedenen Ansichten verteilt. Wenn das Element auf der Seite vorhanden ist, hat es mein JS
VegaStudios am
So nützlich, danke!
sc_props
113

Es scheint, dass document.getElementById('overlayBtn');das zurückkehrtnull da es ausgeführt wird, bevor das DOM vollständig geladen ist.

Wenn Sie diese Codezeile unter setzen

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

dann läuft es ohne probleme.

Beispiel:

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
quelle
23

Ich sah mich einer ähnlichen Situation gegenüber. Dies liegt wahrscheinlich daran, dass das Skript ausgeführt wird, bevor die Seite geladen wird. Durch Platzieren des Skripts am Ende der Seite habe ich das Problem umgangen.

sridhar
quelle
1
Ja, ich denke, es gibt je nach Szenario mehrere Lösungen für dieses Problem.
RPEG
16

Ich habe den gleichen Fehler erhalten, aber die Durchführung einer Nullprüfung schien nicht zu helfen.

Die Lösung, die ich gefunden habe, bestand darin, meine Funktion in einen Ereignis-Listener zu packen, damit das gesamte Dokument überprüft, wann das DOM vollständig geladen wurde.

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

Ich denke, das liegt daran, dass ich ein Framework (Angular) verwende, das meine HTML-Klassen und IDs dynamisch ändert.

MattSidor
quelle
1
Ich habe das gleiche Problem, wenn ich mit Electron spiele. Speichern Sie es mit der gleichen Methode.
Charles
9

Es ist nur so, dass Ihr JS vor dem HTML-Teil geladen wird und dieses Element daher nicht gefunden werden kann. Fügen Sie einfach Ihren gesamten JS-Code in eine Funktion ein, die beim Laden des Fensters aufgerufen wird.

Sie können Ihren Javascript-Code auch unter dem HTML-Code einfügen.

Ajit Kumar
quelle
8

Das Skript wird vor dem Text geladen. Das Skript bleibt nach dem Inhalt erhalten

Sagar M.
quelle
5

Setzen Sie das Skript am Ende des Body-Tags.

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

Vielen Dank an @Rob M. für seine Hilfe. So sah der letzte Codeblock aus:

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
quelle
2

Ich habe einfach 'async' zu meinem Skript-Tag hinzugefügt, was das Problem anscheinend behoben hat. Ich bin mir nicht sicher warum, wenn jemand es erklären kann, aber es hat bei mir funktioniert. Ich vermute, dass die Seite nicht auf das Laden des Skripts wartet, also wird die Seite gleichzeitig mit dem JavaScript geladen.

Async / Await ermöglicht es uns, asynchronen Code synchron zu schreiben. Es ist nur syntaktischer Zucker, der Generatoren und Yield-Anweisungen verwendet, um die Ausführung anzuhalten, sodass wir ihn einer Variablen zuweisen können!

Hier ist der Referenzlink: https://medium.com/siliconwat/how-javascript-async-await-works-3cab4b7d21da

Andy Smith
quelle
2

Ich bin auf dasselbe Problem gestoßen und habe nach null gesucht, aber es hat nicht geholfen. Weil das Skript vor dem Laden der Seite geladen wurde. Nur durch Platzieren des Skripts vor dem End-Body-Tag wurde das Problem gelöst.

Mahmud
quelle
0

Wie andere gesagt haben, besteht das Problem darin, dass das Skript ausgeführt wird, bevor die Seite (und insbesondere das Zielelement) geladen wird.

Aber ich mag die Lösung der Neuordnung des Inhalts nicht.

Die bevorzugte Lösung besteht darin, einen Ereignishandler auf das Ereignis zum Laden der Seite zu setzen und den Listener dort festzulegen. Dadurch wird sichergestellt, dass die Seite und das Zielelement geladen werden, bevor die Zuweisung ausgeführt wird. z.B

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

    <body onload="onLoadFunct()" ....>
    .....
pjm
quelle
0

Ich habe eine Sammlung von Zitaten zusammen mit Namen. Ich verwende die Schaltfläche "Aktualisieren", um das letzte mit einem bestimmten Namen verknüpfte Zitat zu aktualisieren. Wenn Sie jedoch auf die Schaltfläche "Aktualisieren" klicken, wird es nicht aktualisiert. Ich füge unten Code für die Datei server.js und die externe Datei js (main.js) ein.

main.js (externes 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 Datei

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
quelle
0

Vielen Dank, laden Sie die Skripte auf bestimmte Seiten, die Sie verwenden, nicht für alle Seiten, manchmal mit swiper.js oder einer anderen Bibliothek. Dies kann zu dieser Fehlermeldung führen. Dies ist die einzige Möglichkeit, dieses Problem zu lösen, indem die JS-Bibliothek auf bestimmten Seiten geladen wird Diese ID ist vorhanden und verhindert das Laden derselben Bibliothek auf allen Seiten.

Hoffe das hilft dir.

Baseer Ebadi
quelle
0

Ich hatte das gleiche Problem, aber mein Ausweis war vorhanden. Also habe ich versucht, "window.onload = init;" hinzuzufügen. Dann habe ich meinen ursprünglichen JS-Code mit einer Init-Funktion versehen (nennen Sie es wie Sie wollen). Dies funktionierte, also fügte ich zumindest in meinem Fall einen Ereignis-Listener hinzu, bevor mein Dokument geladen wurde. Dies könnte auch das sein, was Sie erleben.

ultrageek
quelle
-1

Dies liegt daran, dass das Element zum Zeitpunkt der Ausführung des Bundles js noch nicht geladen war.

Ich würde <script src="sample.js" type="text/javascript"></script>das ganz unten in der index.htmlDatei verschieben. Auf diese Weise können Sie sicherstellen, dass das Skript ausgeführt wird, nachdem alle HTML-Elemente analysiert und gerendert wurden.

Xcode
quelle
Falsch. Das ist altmodisches Denken. Das Laden am Ende verzögert das Laden, wie Sie angegeben haben, stellt jedoch nicht sicher, dass das DOM vollständig gezeichnet ist . Ältere Seiten, die diesen Hack verwendet haben, konnten nicht ausgeführt werden, da die DOM-Zeichnung langsamer als das Laden war. Diese Antwort stellt sicher, dass das DOM vor der Ausführung gezeichnet wird.
Machavity
-3

Fügen Sie alle Ereignis-Listener hinzu, wenn ein Fenster geladen wird. Arbeitet wie ein Zauber, egal wo Sie Skript-Tags platzieren.

window.addEventListener("load", startup);

function startup() {

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

}

myFunc(){}
Natalie Jimenez
quelle
Das Zeichnen der Seite kann manchmal länger dauern als das Laden des Skripts, daher ist die Position nicht in allen Fällen so wichtig. Das Hinzufügen eines Listeners ist der bevorzugte Weg, wird jedoch loadaus demselben Grund auch nicht mehr empfohlen. DOMContentLoaded ist der bevorzugte Weg, da es erst ausgelöst wird, nachdem das DOM vollständig gezeichnet wurde.
Machavity
Danke, ich werde es versuchen. Ich habe meine Antwort vom Mozilla-Netzwerk erhalten. Ich dachte, es sei eine vertrauensvolle Quelle.
Natalie Jimenez