Impossibile leggere la proprietà "addEventListener" di null


106

Devo usare JavaScript vanilla per un progetto. Ho alcune funzioni, una delle quali è un pulsante che apre un menu. Funziona sulle pagine in cui esiste l'id di destinazione, ma provoca un errore nelle pagine in cui l'id non esiste. Nelle pagine in cui la funzione non riesce a trovare l'id, ricevo un errore "Impossibile leggere la proprietà 'addEventListener' di null" e nessuna delle mie altre funzioni funziona.

Di seguito è riportato il codice del pulsante che apre il 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;
};

Come lo gestisco? Probabilmente ho bisogno di racchiudere tutto questo codice in un'altra funzione o utilizzare un'istruzione if / else in modo che cerchi l'ID solo su pagine specifiche, ma non esattamente.


1
puoi mostrare il codice html. sembra che non riesca a trovare l'elemento con ID 'overlayBtn'
BlaShadow

2
Nelle pagine in cui la funzione non riesce a trovare l'id, ricevo un errore "Impossibile leggere la proprietà 'addEventListener' di null" e nessuna delle mie altre funzioni funziona. Penso che la risposta fosse più o meno nella domanda. Non sei riuscito a trovare l'elemento, quindi non puoi aggiungere un ascoltatore di eventi ad esso ...
Etai,

1
Può semplicemente accadere se hai usato classnel tuo html invece di ide hai richiesto un getElementByIdnei tuoi script.
Deke

Risposte:


198

Penso che l'approccio più semplice sarebbe semplicemente controllare che elnon sia nullo prima di aggiungere un listener di eventi:

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

eccezionale. quello ha funzionato. Ho anche spostato la funzione onclick in quell'istruzione if. Ho pubblicato il codice finale di seguito.
morocklo

3
sarà nullprima che il componente di reazione venga montato!

Grazie amico: D Esattamente quello che stavo cercando ... Ho più ascoltatori nella mia app e gli ascoltatori sono distribuiti in diverse visualizzazioni. Se l'elemento è presente sulla pagina, stava rovinando il mio JS
VegaStudios

Così utile, grazie!
sc_props

113

Sembra che document.getElementById('overlayBtn');stia tornando nullperché viene eseguito prima del caricamento completo del DOM.

Se metti questa riga di codice sotto

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

quindi verrà eseguito senza problemi.

Esempio:

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

Ho affrontato una situazione simile. Ciò è probabilmente dovuto al fatto che lo script viene eseguito prima del caricamento della pagina. Inserendo lo script in fondo alla pagina, ho aggirato il problema.


1
Sì, penso che ci siano più soluzioni a questo problema a seconda dello scenario.
rpeg

16

Stavo ricevendo lo stesso errore, ma l'esecuzione di un controllo nullo non sembrava aiutare.

La soluzione che ho trovato è stata quella di racchiudere la mia funzione all'interno di un listener di eventi per l'intero documento per controllare quando il DOM ha terminato il caricamento.

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

Penso che questo sia perché sto usando un framework (Angular) che sta cambiando le mie classi HTML e ID in modo dinamico.


1
Mi imbatto nello stesso problema quando gioco con Electron. Salvato usando lo stesso metodo.
charles

9

È solo bcz che il tuo JS viene caricato prima della parte HTML e quindi non riesce a trovare quell'elemento. Basta inserire l'intero codice JS all'interno di una funzione che verrà chiamata quando la finestra verrà caricata.

Puoi anche inserire il tuo codice Javascript sotto html.


8

lo script viene caricato prima del corpo, mantieni lo script dopo il contenuto


5

Metti lo script alla fine del tag body.

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

3

Grazie a @Rob M. per il suo aiuto. Ecco come appariva l'ultimo blocco di codice:

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

Ho semplicemente aggiunto "async" al mio tag script, che sembra aver risolto il problema. Non sono sicuro del perché, se qualcuno può spiegare, ma per me ha funzionato. La mia ipotesi è che la pagina non stia aspettando il caricamento dello script, quindi la pagina viene caricata contemporaneamente a JavaScript.

Async / Await ci consente di scrivere codice asincrono in modo sincrono. è solo zucchero sintattico che usa generatori e istruzioni yield per "mettere in pausa" l'esecuzione, dandoci la possibilità di assegnarlo a una variabile!

Ecco il link di riferimento: https://medium.com/siliconwat/how-javascript-async-await-works-3cab4b7d21da


2

Ho riscontrato lo stesso problema e ho verificato la presenza di null ma non ha aiutato. Perché lo script si stava caricando prima del caricamento della pagina. Quindi, solo inserendo lo script prima del tag end body si è risolto il problema.


0

Come altri hanno detto, il problema è che lo script viene eseguito prima che la pagina (e in particolare l'elemento di destinazione) venga caricata.

Ma non mi piace la soluzione di riordinare il contenuto.

La soluzione preferita è mettere un gestore di eventi sull'evento onload della pagina e impostare il Listener lì. Ciò garantirà che la pagina e l'elemento di destinazione vengano caricati prima dell'esecuzione dell'assegnazione. per esempio

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

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

0

Ho una raccolta di citazioni e nomi. Sto usando il pulsante di aggiornamento per aggiornare l'ultima citazione associata a un nome specifico, ma facendo clic sul pulsante di aggiornamento non si aggiorna. Sto includendo il codice di seguito per il file server.js e il file js esterno (main.js).

main.js (js esterno)

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

file 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

Grazie da tutti, Carica gli script in pagine specifiche che usi, non per tutte le pagine, a volte usando swiper.js o altra libreria potrebbe causare questo messaggio di errore, l'unico modo per risolvere questo problema è caricare la libreria JS su pagine specifiche quell'ID esiste e impedisce il caricamento della stessa libreria in tutte le pagine.

Spero che questo ti aiuti.


0

Ho avuto lo stesso problema, ma il mio ID era presente. Quindi ho provato ad aggiungere "window.onload = init;" Quindi ho avvolto il mio codice JS originale con una funzione init (chiamala come vuoi). Ha funzionato, quindi, almeno nel mio caso, stavo aggiungendo un listener di eventi prima che il mio documento venisse caricato. Questo potrebbe essere anche quello che stai vivendo.


-1

Questo perché l'elemento non era stato caricato nel momento in cui veniva eseguito il bundle js.

Sposterei il <script src="sample.js" type="text/javascript"></script>in fondo al index.htmlfile. In questo modo puoi assicurarti che lo script venga eseguito dopo che tutti gli elementi html sono stati analizzati e renderizzati.


Errato. Questo è il pensiero della vecchia scuola. Il caricamento alla fine ritarda il caricamento, come hai affermato, ma non garantisce che il DOM sia completamente disegnato . Ho avuto pagine più vecchie che utilizzavano questo hack che non venivano eseguite perché il disegno del DOM era più lento del caricamento. Questa risposta garantisce che il DOM venga disegnato prima dell'esecuzione.
Machavity

-3

Aggiungi tutti i listener di eventi quando viene caricata una finestra Funziona come un fascino, indipendentemente da dove metti i tag di script.

window.addEventListener("load", startup);

function startup() {

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

}

myFunc(){}

Il disegno della pagina a volte può richiedere più tempo del caricamento dello script, quindi la posizione non è così importante in tutti i casi. L'aggiunta di un listener è il modo preferito, ma loadè anche deprecato per lo stesso motivo. DOMContentLoaded è il modo preferito, poiché si attiva solo dopo che il DOM è stato completamente disegnato.
Machavity

Grazie proverò. Ho ricevuto la mia risposta dalla rete Mozilla. Ho pensato che fosse una fonte fidata.
Natalie Jimenez
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.