Modifica l'URL della barra degli indirizzi nell'app AJAX in modo che corrisponda allo stato corrente


166

Sto scrivendo un'app AJAX, ma mentre l'utente si sposta attraverso l'app, vorrei che l'URL nella barra degli indirizzi si aggiornasse nonostante la mancanza di ricariche di pagina. Fondamentalmente, vorrei che potessero aggiungere un segnalibro in qualsiasi momento e quindi tornare allo stato attuale.

In che modo le persone gestiscono il mantenimento della RESTfulness nelle app AJAX?


2
Viene utilizzato per identificare lo stato delle tue app, ma non ha nulla a che fare con "RESTfulness".
Mohamed,

29
window.history.pushState(null,'hi','page1?id=32')
Omu,

3
la risposta accettata è stata scritta 5 anni fa e nel frattempo abbiamo ottenuto window.history.pushState, proprio come ha detto @Omu. location.hash ha portato numerosi problemi ed è meglio evitarlo.
pcarvalho,

Ho modificato la risposta per rendere prominente l'approccio pushState.
jasonjwwilliams

Risposte:


116

Il modo per farlo è manipolare location.hashquando gli aggiornamenti AJAX comportano una modifica dello stato che desideri avere un URL discreto. Ad esempio, se l'URL della tua pagina è:

http://example.com/

Se una funzione lato client ha eseguito questo codice:

// AJAX code to display the "foo" state goes here.

location.hash = 'foo';

Quindi, l'URL visualizzato nel browser verrà aggiornato in:

http://example.com/#foo

Ciò consente agli utenti di contrassegnare lo stato "pippo" della pagina e utilizzare la cronologia del browser per navigare tra gli stati.

Con questo meccanismo in atto, dovrai quindi analizzare la parte hash dell'URL sul lato client utilizzando JavaScript per creare e visualizzare lo stato iniziale appropriato, poiché gli identificatori di frammento (la parte dopo il #) non vengono inviati al server.

Il plug-in di hashchange di Ben Alman rende quest'ultimo un gioco da ragazzi se stai usando jQuery.


Sembra che tu abbia ragione. Questo è l'unico approccio. Questa sembra una buona spiegazione dettagliata del tuo consiglio: < ajaxpatterns.org/Unique_URLs >
jasonjwwilliams

@buymeasoda Grazie per la modifica; Non sono sicuro di cosa stavo pensando quando ho scritto quella parte.
Dave Ward,

1
Caspita, questa risposta è stata molto utile. Sebbene gli esempi di URL siano un po 'confusi, SO potrebbe sostituire automaticamente i collegamenti con titoli. Che ne dici di sostituire quelli con qualcosa come example.com ed example.com/#foo, in modo che possiamo vedere l'intero URL in testo normale.
Neil,

4
@Pascal Puoi, ma solo nei browser che supportano il pushState di HTML5. Buone informazioni su questo qui: diveintohtml5.info/history.html
Dave Ward

1
Ho finito per essere un grande fan di history.js per coprire le basi della compatibilità del browser github.com/andreasbernhard/history.js
jocull,

18

Guarda siti come book.cakephp.org. Questo sito modifica l'URL senza utilizzare l'hash e utilizzare AJAX. Non sono sicuro di come lo faccia esattamente, ma ho cercato di capirlo. Se qualcuno lo sa, fammelo sapere.

Inoltre github.com durante la navigazione all'interno di un determinato progetto.


L'ho notato con GitHub circa una settimana fa. Come mai lo fanno? Deve tornare indietro e controllare.
Drew Noakes,

16
Sembrano usare la funzione javascript pushState (). Questo aggiunge alla cronologia del tuo browser. Guardaci dentro; è piuttosto interessante e interessante.
daniel.wright il

Grazie per questo, era esattamente quello che stavo cercando. Mi ero chiesto come facesse Github. All'inizio ho pensato che dovesse essere ricaricato, ma c'erano solo richieste AJAX. In Opera, ha ricaricato la pagina.
kamranicus,

Una tecnica simile viene utilizzata da fb durante la navigazione tra le pagine di diversi gruppi. Hai una colonna di navigazione a sinistra in cui sono menzionati gruppi diversi. Quando si fa clic sul nome di un determinato gruppo, l'URL cambia e cambia solo il contenuto del riquadro del contenuto principale insieme all'URL (senza hash). Pertanto, quando l'utente ricarica la pagina, non vengono reindirizzati alla home page ma alla pagina dei gruppi.
Madeyedexter,


11

Questo è simile a quello che ha detto Kevin. Puoi avere il tuo stato client come qualche oggetto javascript e quando vuoi salvare lo stato, serializzi l'oggetto (usando la codifica JSON e base64). È quindi possibile impostare il frammento di href su questa stringa.

var encodedState = base64(json(state));
var newLocation = oldLocationWithoutFragment + "#" + encodedState;

document.location = newLocation; // adds new entry in browser history
document.location.replace(newLocation); // replaces current entry in browser history

Il primo modo tratterà il nuovo stato come una nuova posizione (quindi il pulsante Indietro li porterà alla posizione precedente). Quest'ultimo no.


C'è un modo per aggiungere una voce alla cronologia dei segnalibri senza aggiornare la pagina? L'impostazione della posizione (come nel tuo primo esempio) causerà un aggiornamento, no?
Drew Noakes,

facendo document.location.replace reindirizzerà anche il browser a quell'URL (appena provato nella console di Chrome)
Omu,

3

SWFAddress funziona nei progetti Flash e Javascript e ti consente di creare URL con segnalibri (usando il metodo hash sopra menzionato) oltre a offrirti il ​​supporto per il pulsante Indietro.

http://www.asual.com/swfaddress/


3

Il metodo window.location.hash è il modo preferito di fare le cose. Per una spiegazione su come farlo, Ajax Patterns - URL univoci .

YUI ha un'implementazione di questo modello come modulo, che include soluzioni specifiche di IE per far funzionare il pulsante Indietro e riscrivere l'indirizzo usando l'hash. YUI Browser History Manager .

Anche altri framework hanno implementazioni simili. Il punto importante è che se vuoi che la cronologia funzioni insieme alla riscrittura dell'indirizzo, i diversi browser hanno bisogno di modi diversi di gestirla. (Questo è dettagliato nel primo articolo di collegamento.)

IE ha bisogno di un hack basato su iframe, in cui Firefox produrrà una doppia cronologia usando lo stesso metodo.


3

Se OP o altri stanno ancora cercando un modo per modificare la cronologia del browser per abilitare lo stato, usare pushState e replaceState, come suggerito da IESUS, è il modo "giusto" per farlo ora. Il vantaggio principale rispetto a location.hash sembra essere che crea URL reali, non solo hash. Se la cronologia del browser che utilizza gli hash viene salvata e quindi rivisitata con javascript disabilitato, l'app non funzionerà, poiché gli hash non vengono inviati al server. Tuttavia, se è stato utilizzato pushState, l'intero percorso verrà inviato al server, che sarà quindi possibile creare per rispondere in modo appropriato ai percorsi. Ho visto un esempio in cui sono stati utilizzati gli stessi modelli di baffi sia sul lato server che sul lato client. Se il client avesse javascript abilitato, otterrebbe risposte rapide evitando il roundtrip al server, ma l'app funzionerebbe perfettamente senza il javascript. Pertanto, l'app può degradarsi con grazia in assenza di JavaScript.

Inoltre, credo che ci sia qualche framework là fuori, con un nome come history.js. Per i browser che supportano HTML5, utilizza pushState, ma se il browser non lo supporta, ricorre automaticamente all'utilizzo degli hash.


2

Controlla se l'utente è "nella" pagina, quando fai clic sulla barra dell'URL, JavaScript indica che sei fuori pagina. Se cambi la barra dell'URL e premi 'INVIO' con il simbolo '#' al suo interno, vai di nuovo nella pagina, senza fare clic sulla pagina manualmente con il cursore del mouse, quindi un comando di evento keyboad (document.onkeypress) da JavaScript essere in grado di verificare se è inserito e attivo il javascript per il reindirizzamento. Puoi verificare se l'utente è nella pagina con window.onfocus e verificare se è fuori con window.onblur.

Sì, è possibile.

;)


Questo è il modo in cui ho visto elegante cambiare la pagina quando l'utente modifica la barra dell'URL con il simbolo #.
Marcelo,
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.