Perché jQuery o un metodo DOM come getElementById non trovano l’elemento?

Quali sono le possibili ragioni per document.getElementById , $("#id") o qualsiasi altro metodo DOM / selettore jQuery che non trova gli elementi?

I problemi di esempio includono:

jQuery silenziosamente non riesce a associare un gestore di eventi e un metodo DOM standard restituisce null risultante nell’errore:

Uncaught TypeError: imansible impostare la proprietà ‘…’ di null

L’elemento che stavi cercando di trovare non era nel DOM quando è stato eseguito lo script.

La posizione del tuo script dipendente da DOM può avere un profondo effetto sul suo comportamento. I browser analizzano i documenti HTML dall’alto verso il basso. Gli elementi vengono aggiunti al DOM e gli script vengono (generalmente) eseguiti mentre vengono incontrati. Ciò significa che l’ordine conta. Tipicamente, gli script non riescono a trovare gli elementi che appaiono in seguito nel markup perché questi elementi devono ancora essere aggiunti al DOM.

Considera il seguente markup; script # 1 non riesce a trovare il

mentre lo script # 2 ha esito positivo:

  
test div

Breve e semplice: perché gli elementi che stai cercando non esistono nel documento (ancora).


Per il resto di questa risposta userò getElementById come esempio, ma lo stesso vale per getElementsByTagName , querySelector e qualsiasi altro metodo DOM che seleziona gli elementi.

Possibili motivi

Ci sono due ragioni per cui un elemento potrebbe non esistere:

  1. Un elemento con l’ID passato non esiste realmente nel documento. Dovresti ricontrollare che l’ID che passi a getElementById corrisponda realmente a un ID di un elemento esistente nel codice HTML (generato) e che non hai scritto male l’ID (gli ID fanno distinzione tra maiuscole e minuscole !).

    Per inciso, nella maggior parte dei browser contemporanei , che implementano i querySelector() e querySelectorAll() , la notazione in stile CSS viene utilizzata per recuperare un elemento tramite il suo id , ad esempio: document.querySelector('#elementID') , in contrapposizione a il metodo con cui un elemento viene recuperato dal suo id sotto document.getElementById('elementID') ; nel primo il carattere # è essenziale, nel secondo si otterrebbe che l’elemento non venga recuperato.

  2. L’elemento non esiste nel momento in cui chiami getElementById .

Quest’ultimo caso è abbastanza comune. I browser analizzano ed elaborano l’HTML dall’alto verso il basso. Ciò significa che qualsiasi chiamata a un elemento DOM che si verifica prima che l’elemento DOM appaia nell’HTML, avrà esito negativo.

Considera il seguente esempio:

  

Il div appare dopo la script . Al momento lo script è eseguito, l’elemento non esiste ancora e getElementById restituirà null .

jQuery

Lo stesso vale per tutti i selettori con jQuery. jQuery non troverà elementi se hai sbagliato a digitare il tuo selettore o stai provando a selezionarli prima che esistano realmente .

Un ulteriore vantaggio è quando jQuery non viene trovato perché hai caricato lo script senza protocollo e stai eseguendo dal file system:

  

questa syntax viene utilizzata per consentire lo script da caricare tramite HTTPS su una pagina con protocollo https: // e per caricare la versione HTTP su una pagina con protocollo http: //

Ha lo sfortunato effetto collaterale di tentare e fallire nel caricare file://somecdn.somewhere.com...


soluzioni

Prima di effettuare una chiamata a getElementById (o qualsiasi altro metodo DOM), assicurati che gli elementi a cui vuoi accedere esistano, cioè che il DOM sia caricato.

Questo può essere garantito semplicemente inserendo il tuo JavaScript dopo il corrispondente elemento DOM

 

in tal caso puoi anche inserire il codice subito prima del tag body di chiusura ( ) (tutti gli elementi DOM saranno disponibili al momento dell’esecuzione dello script).

Altre soluzioni includono l’ascolto degli eventi di load [MDN] o DOMContentLoaded [MDN] . In questi casi non importa dove nel documento si inserisce il codice JavaScript, è sufficiente ricordare di inserire tutto il codice di elaborazione DOM nei gestori di eventi.

Esempio:

 window.onload = function() { // process DOM elements here }; // or // does not work IE 8 and below document.addEventListener('DOMContentLoaded', function() { // process DOM elements here }); 

Si prega di consultare gli articoli su quirksmode.org per ulteriori informazioni sulla gestione degli eventi e sulle differenze tra browser.

jQuery

Prima assicurati che jQuery sia caricato correttamente. Utilizza gli strumenti di sviluppo del browser per scoprire se il file jQuery è stato trovato e correggere l’URL se non lo era (ad esempio aggiungi lo schema http: o https: all’inizio, aggiusta il percorso, ecc.)

Ascoltare gli eventi load / DOMContentLoaded è esattamente ciò che jQuery sta facendo con .ready() [docs] . Tutto il codice jQuery che influenza l’elemento DOM dovrebbe essere all’interno di quel gestore di eventi.

In effetti, il tutorial di jQuery afferma esplicitamente:

Poiché quasi tutto ciò che facciamo quando si usa jQuery legge o manipola il modello di object documento (DOM), dobbiamo assicurarci di iniziare ad aggiungere eventi, ecc. Non appena il DOM è pronto.

Per fare ciò, registriamo un evento pronto per il documento.

 $(document).ready(function() { // do stuff when DOM is ready }); 

In alternativa puoi anche usare la syntax abbreviata:

 $(function() { // do stuff when DOM is ready }); 

Entrambi sono equivalenti.

Ragioni per cui i selettori basati su id non funzionano

  1. L’elemento / DOM con id specificato non esiste ancora.
  2. L’elemento esiste, ma non è registrato nel DOM [nel caso di nodes HTML aggiunti dynamicmente dalle risposte Ajax].
  3. È presente più di un elemento con lo stesso id che causa un conflitto.

soluzioni

  1. Prova ad accedere all’elemento dopo la sua dichiarazione o usa in alternativa roba come $(document).ready();

  2. Per gli elementi provenienti dalle risposte Ajax, usa il metodo .bind() di jQuery. Le versioni precedenti di jQuery avevano .live() per lo stesso.

  3. Utilizza gli strumenti [ad esempio, il plugin webdeveloper per i browser] per trovare gli ID duplicati e rimuoverli.

Come ha sottolineato @FelixKling, lo scenario più probabile è che i nodes che stai cercando non esistano (ancora).

Tuttavia, le moderne pratiche di sviluppo possono spesso manipolare elementi di documento all’esterno dell’albero del documento con DocumentFragments o semplicemente staccando / ricollegando direttamente gli elementi correnti. Tali tecniche possono essere utilizzate come parte del templating di JavaScript o per evitare eccessive ridipinture / operazioni di reflow mentre gli elementi in questione vengono pesantemente modificati.

Allo stesso modo, la nuova funzionalità “Shadow DOM” che viene implementata attraverso i browser moderni consente agli elementi di essere parte del documento, ma non alla query da parte di document.getElementById e tutti i suoi metodi fratelli (querySelector, ecc.). Questo è fatto per incapsulare funzionalità e in particolare nasconderlo.

Di nuovo, tuttavia, è molto probabile che l’elemento che stai cercando semplicemente non sia (ancora) nel documento, e dovresti farlo come suggerisce Felix. Tuttavia, dovresti anche essere consapevole del fatto che questo non è sempre più l’unico motivo per cui un elemento potrebbe essere introvabile (temporaneamente o permanentemente).

Se l’elemento a cui stai tentando di accedere è all’interno di un iframe e provi ad accedervi al di fuori del contesto iframe ciò causerà anche il suo fallimento.

Se vuoi ottenere un elemento in un iframe, puoi scoprire come.

Prova a inserire document.getElementById in setTimeout()

Per esempio

 setTimeout(function(){ console.log(document.getElementById('whatever')); }, 100); 

Se funziona, allora è solo un problema di temporizzazione.