2009-08-03 13 views
8

Questo è generalmente il modo in cui gestisco il miglioramento progressivo pur mantenendo l'esperienza pulita, ma quanto è sicuro? c'è il potenziale per una condizione di gara e questo non funziona?È corretto manipolare dom prima dello stato di pronto?

immaginare il semplice scenario astratto, si desidera visualizzare qualcosa in modo diverso se si dispone di supporto javascript .. questo è generalmente ciò che io voglio finire per fare:

<div id="test">original</div> 
<script type="text/javascript"> 
    var t = document.getElementById('test'); 
    t.innerHTML = 'changed'; 
</script> 

Molti possono rivendicare è necessario utilizzare un quadro e attendere per un evento domready, e fare le modifiche lì .. tuttavia c'è un ritardo significativo in cui l'elemento 'test' sarà già stato reso prima della fine del documento e il css è pronto e un domready si innesca .. causando così uno sfarfallio notabile di "originale".

Questo codice è soggetto a guasti delle condizioni di gara? o posso garantire che un elemento sia individuabile e modificabile se esiste prima della sceneggiatura?

Grazie in anticipo.

risposta

5

È possibile, ma ci sono problemi che lo circondano.

Prima di tutto, in IE se si tenta di manipolare un nodo che non è stato chiuso (ad esempio BODY prima del tag di chiusura che dovrebbe essere sotto il JS), è possibile riscontrare l'errore "OPERATION ABORTED" di IE che determinerà un pagina vuota. La manipolazione di un nodo include nodi aggiunti, nodi in movimento, ecc.

In altri browser il comportamento non è definito, tuttavia generalmente si comportano come ci si aspetterebbe. Il problema principale è che man mano che la pagina si evolve, la pagina potrebbe caricarsi/analizzare/eseguire in modo diverso. Ciò potrebbe causare l'esecuzione di alcuni script prima che un browser definisca gli elementi di riferimento effettivamente creati e resi disponibili per la manipolazione DOM.

Se si sta tentando di migliorare le prestazioni percepite dall'utente (ad esempio fastidio). Ti consiglio caldamente di evitare questo percorso e di alleggerire le tue pagine. Puoi utilizzare Yahoo's YSlow/Google Page Performance Firebug per aiutarti a iniziare.

Google's Page Speed

Yahoo's YSlow

+0

Ciao Raegx, sì, posso capire completamente l'operazione problema interrotto con elementi che cambiano che non sono stati chiusi .. in termini di viscosità, queste pagine sono chiare, la pagina effettiva è 15kb .. tuttavia il mio elemento modificato potrebbe essere proprio sotto il tag del corpo di apertura, e renderà il rendering prima che domready fires, indipendentemente da quanto sia leggera la mia pagina .. Sto cercando di evitare un'esperienza sciatta questo è sempre vissuto con domino e facendo questo genere di cose. – meandmycode

+0

Indietro nei periodi bui, quando non avevamo un modo cross-browser per sparare suDomReady, usavamo onLoad, che sparava dopo che tutte le immagini/css/etc erano state caricate e renderizzate. Ora abbiamo onDomReady che si attiva dopo che il DOM è stato analizzato e rappresentato, ma potenzialmente prima di immagini/etc. Anche questo è un progresso relativamente nuovo. Quindi aspettare OnDomReady è tutto ciò che abbiamo a questo punto e rappresenta la migliore soluzione per la robustezza. Se ritieni che la tua manipolazione prima di onDomReady valga la pena e tu non stia aggiungendo/creando/spostando nodi su nodi non chiusi, probabilmente stai bene. –

+0

Grande, ne vale sicuramente la pena se funziona .. da quello che sto ascoltando, dovrebbe funzionare bene ma non c'è nulla che affermi ufficialmente che un elemento dovrebbe essere pronto dopo il suo nodo di chiusura. – meandmycode

3

È possibile manipolare il DOM prima che sia completamente caricato, ma può essere rischioso. Ovviamente non puoi garantire che il bit del DOM che stai tentando di manipolare esista ancora, quindi il tuo codice potrebbe non funzionare a intermittenza.

+0

Grazie rikh, che cosa vuoi dire non c'è nessun garanzia, dalla specifica o mediante effettiva realtà di prodotti che esistono oggi (ff, ie, opera, ecc.). Penso che il parser agisce in modo lineare e aggiunge elementi mentre incontra il loro nodo di chiusura ..mentre questo potrebbe non essere una specificazione, penserei che questo è un comportamento ragionevole, ed era più alla ricerca di risposte autorevoli che questo è il caso. – meandmycode

+1

Per essere onesti, non lo so, ma non è qualcosa su cui vorrei dipendere. Se sei veramente preoccupato di visualizzare le informazioni errate, prova a non visualizzare nulla all'inizio, quindi a compilare qualcosa su doc ​​ready o semplicemente a progettare il problema fuori dal sistema, in modo da non dover fare quello che stai chiedendo. –

+0

Purtroppo questo non è possibile, l'ultimo esempio che ho è dove vengono visualizzati i numeri di impaginazione come collegamenti ipertestuali, e il nostro javascript esegue e modifica questi in modo che possiamo visualizzare 'Pagina x di y' ed evidenziare il collegamento ipertestuale della pagina attivo (le pagine sono anchors) .. questo è un tipico scenario di miglioramento progressivo in cui rendiamo disponibile qualcosa che funzionerà senza javascript .. e quindi intercettiamo e modificiamo con javascript per poter utilizzare javascript .. il fatto che tu possa manipolarlo con javascript ti provi. .avere il supporto per javascript;) – meandmycode

1

Finché si modificano solo i nodi che precedono il blocco di script (ovvero tag di chiusura del nodo precede tag di apertura dello script), non si dovrebbe incontrare alcun problema.

Se si desidera assicurarsi che l'operazione abbia esito positivo, avvolgere il codice in un blocco try...catch e richiamarlo di nuovo tramite setTimeout() in caso di errore.

+0

Grazie Christoph, stavo considerando che al momento del fallimento non avrei ottenuto nulla o un'eccezione e avrei potuto riprovare .. anche se non mi piace molto la logica dei tentativi, temo che l'esecuzione possa ostacolare il caricamento della pagina. vado a vedere se riesco a eseguire alcuni test cercando di simulare una larghezza di banda molto limitata e anche una potenza di elaborazione bassa per vedere se riesco a trovare qualsiasi finestra a tutto ciò che esiste .. finora la larghezza di banda non sembra fare nulla, ho eseguito iterazioni del caricamento della pagina a 100 byte al secondo (ci vuole un po ') .. e al momento in cui l'area è stata caricata ha già ... – meandmycode

+0

.. ha eseguito lo script perfettamente bene .. Immagino che il tempo di elaborazione limitato sia molto più probabile storpiare il parser e illuminare tutte le finestre in cui l'ipotesi è sbagliata. – meandmycode

0

In Viajeros.com ho un indicatore di caricamento funzionante da 8-9 mesi e non ho avuto problemi fino ad ora. Ecco come si presenta:

<body> 

<script type="text/javascript"> 
    try { 
     document.write('<div id="cargando"><p>Cargando...<\/p><\/div>'); 
     document.getElementById("cargando").style.display = "block"; 
    } catch(E) {}; 
</script> 
+2

Forse non è tutto il codice, ma ti rendi conto che il 'getElementById' è completamente inutile, giusto? Puoi semplicemente aggiungere 'style =" display: block "' al codice HTML. – DisgruntledGoat

-1

Accesso al DOM getta prematuramente eccezioni in IE 5 e Navigator 4.

Problemi correlati