Ajax, pulsante Indietro e aggiornamenti DOM


113

Se javascript modifica il DOM nella pagina A, l'utente passa alla pagina B e quindi preme il pulsante Indietro per tornare alla pagina A. Tutte le modifiche al DOM della pagina A vengono perse e all'utente viene presentata la versione originariamente recuperata dal server.

Funziona in questo modo su stackoverflow, reddit e molti altri siti web popolari. (prova ad aggiungere un commento di prova a questa domanda, quindi vai a una pagina diversa e premi il pulsante Indietro per tornare indietro - il tuo commento sarà "andato")

Ciò ha senso, tuttavia alcuni siti Web (apple.com, basecamphq.com ecc.) In qualche modo costringono il browser a fornire all'utente lo stato più recente della pagina. (vai su http://www.apple.com/ca/search/?q=ipod , fai clic sul link Download in alto e quindi fai clic sul pulsante Indietro: tutti gli aggiornamenti DOM verranno conservati)

da dove viene l'incoerenza?


È interessante notare che Apple sta ricordando lo stato senza modificare l'hash .. hmmm
James

Apple sembra che stiano solo manipolando la cache delle risposte
BigBlondeViking

Come altri hanno già suggerito, questo non è qualcosa correlato a javascript o ajax. Dovresti rimuovere questi tag per ottenere risposte corrette.
BYK

L'esempio di Apple è scarso. Se si contratta un'area di ricerca [es: prodotti], fare clic sul collegamento, quindi premere Indietro, il DOM non viene conservato. stai cercando una soluzione hash che molti hanno suggerito.
BigBlondeViking

Quando premo il pulsante Indietro, Apple non ricorda affatto la pagina dei risultati di ricerca in cui mi trovavo. Utilizzando IE7. Hai bisogno di una soluzione hash. Vedi: Facebook.
Josh Stodola

Risposte:


106

Una risposta: tra le altre cose, gli eventi di scaricamento causano l'invalidazione della cache di ritorno / inoltro .

Alcuni browser memorizzano lo stato corrente dell'intera pagina web nella cosiddetta "bfcache" o "cache della pagina". Ciò consente loro di rieseguire il rendering della pagina molto rapidamente durante la navigazione tramite i pulsanti Indietro e Avanti e preserva lo stato del DOM e di tutte le variabili JavaScript. Tuttavia, quando una pagina contiene eventi onunload, tali eventi potrebbero potenzialmente mettere la pagina in uno stato non funzionale, quindi la pagina non viene memorizzata nella bfcache e deve essere ricaricata (ma può essere caricata dalla cache standard) e renderizzato da zero, inclusa l'esecuzione di tutti i gestori onload. Quando si torna a una pagina tramite bfcache, il DOM viene mantenuto nel suo stato precedente, senza la necessità di attivare i gestori onload (perché la pagina è già caricata).

Si noti che il comportamento di bfcache è diverso dalla cache del browser standard per quanto riguarda Cache-Control e altre intestazioni HTTP. In molti casi, i browser memorizzeranno una pagina nella cache bfcache anche se non la memorizzerebbero altrimenti nella cache standard.

jQuery allega automaticamente un evento di scaricamento alla finestra, quindi sfortunatamente l'utilizzo di jQuery squalificherà la tua pagina dall'archiviazione nella bfcache per la conservazione del DOM e il ritorno / avanzamento rapido. [Aggiornamento: questo è stato corretto in jQuery 1.4 in modo che si applichi solo a IE]


3
l'hai completamente inchiodato. entrambi, reddit e stackoverflow utilizzano jquery mentre basecamp e apple utilizzano prototypejs. questo spiega praticamente tutto.
lubos hasko

+1 interessante (non cross browser però) la domanda è molto diversa da quando è iniziata ...
BigBlondeViking

1
probabilmente sarà cross-browser perché posso riprodurlo anche sul mio Internet Explorer. Sono sicuro che ogni browser web con javascript abilitato ha dovuto affrontare comunque questo problema. ma questo è davvero un casino, se ci pensi, il pulsante Indietro dovrebbe sempre portare le persone alla pagina che hanno visto l'ultima volta con tutti gli aggiornamenti DOM, lo stato javascript ecc. Gli sviluppatori non dovrebbero interromperlo facendo qualcosa nell'evento di scaricamento e se lo fanno, i browser web non dovrebbero provare a risolvere il problema non utilizzando affatto bfcache. l'intero evento di scaricamento è un grande scherzo. Sono sicuro che il 99% del tempo viene utilizzato per riparare le perdite di memoria.
lubos hasko

1
In particolare, perdite di memoria di IE. :) L'evento jQuery unload capita anche di correggere un bug (completamente non correlato) in Firefox 2. Ma non è necessario per altri browser. dev.jquery.com/ticket/3015 Suppongo di aver sentito parlare di altri usi per onunload, come il monitoraggio dei clic in uscita o il salvataggio dello stato della webapp, ma non ho mai avuto un motivo per usarlo da solo e se gli sviluppatori vogliono fare il loro siti più lenti e più dolorosi per i loro utenti (odio come tornare alle pagine dei commenti di reddit resetti lo stato di compressione dei commenti), questa è la loro prerogativa.
Miglia

1
L'evento di scaricamento è allegato solo per IE, non per Firefox e Chrome. L'ultima versione di safari preserva lo stato dom senza che lo sviluppatore debba fare nulla.
David

15

Ho cercato di convincere Chrome a comportarsi come Safari e l'unico modo in cui ho scoperto che funziona è impostare Cache-control: no-storele intestazioni. Ciò forza il browser a recuperare nuovamente la pagina dal server quando l'utente preme il pulsante Indietro. Non è l'ideale, ma è meglio che vedersi mostrati una pagina obsoleta.


5
Questa è la risposta corretta alla domanda originale. Se vuoi forzare il ricaricamento di un server con il pulsante Indietro, usa il controllo della cache 'no-store, no-cache, must-revalidate'. Chrome non vuole negozio e IE vuole riconvalidare. Per altri browser (e w3c) non è sufficiente la cache.
woens

3

Facebook ricorda lo stato della pagina modificando l'identificatore hash nell'URL per le richieste ajax. Queste modifiche vengono registrate nella cronologia del browser, quindi quando l'utente fa clic sul pulsante Indietro, l'hash cambia a quello che era prima. Quindi è implicito che avrai bisogno di un po 'di Javascript per monitorare l'identificatore has e reagire quando viene modificato dal browser. Andreas Blixt ha uno script di monitoraggio hash disponibile .


ad oggi non muore, quindi può dirmi cosa fa Facebook ora
Ravinder Payal

3

Questo non ha nulla a che fare con il simbolo cancelletto (#).

Se controlli le intestazioni HTTP di Apple, sta semplicemente memorizzando la pagina nella cache.


L'esempio di Apple è scadente, non stanno "salvando" lo stato della pagina, la sua supposizione che il DOM sia conservato è sbagliato
BigBlondeViking

2

L'utilizzo dell'identificatore hash / frammento dell'URL è un modo abbastanza comune per agganciare / ricordare lo stato in un'applicazione Web che si basa sugli aggiornamenti Ajax e DOM.

Dai un'occhiata al progetto Really Simple History per alcune idee. È possibile monitorare l'URL per le modifiche all'hash, e rsh lo fa, tenendo conto delle differenze del browser.


1

Per chiunque abbia problemi con Railse questo - il tuo problema non è bfcache (pensavo che lo fosse) - è il turbolinksgioiello. Ecco come rimuoverlo.

Spero che questo ti faccia risparmiare tempo e sbatti la testa contro il muro.


0

Quello che stai cercando è un qualche tipo di gestione dell'hash degli URL. Il # nell'URL è solo per il lato client.

Quando modifichi lo stato della schiena con JS, aggiorni i dati nel # dell'url.

Inoltre aggiungi un tipo di polling che monitora se l'hash è cambiato e carica lo stato della pagina in base ai nuovi dati nell'hash.

Guarda questo:

http://ajaxpatterns.org/Unique_URLs


3
questo non ha nulla a che fare con il simbolo cancelletto.
Luca Matteis

3
Ti sbagli, sta cercando il modo più comune per preservare lo stato della pagina in una soluzione AJAX.
BigBlondeViking
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.