Modifique la URL de la barra de direcciones en la aplicación AJAX para que coincida con el estado actual


166

Estoy escribiendo una aplicación AJAX, pero a medida que el usuario se mueve a través de la aplicación, me gustaría que la URL en la barra de direcciones se actualice a pesar de la falta de recarga de la página. Básicamente, me gustaría que puedan marcar en cualquier momento y, por lo tanto, volver al estado actual.

¿Cómo manejan las personas el mantenimiento de RESTfulness en las aplicaciones AJAX?


2
Se utiliza para controlar el estado de sus aplicaciones, pero no tiene nada que ver con "RESTfulness".
Mohamed

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

3
la respuesta aceptada se escribió hace 5 años y, mientras tanto, obtuvimos window.history.pushState, tal como dijo @Omu. the location.hash trajo numerosos problemas y es mejor evitarlo.
pcarvalho

He editado la respuesta para hacer que el enfoque pushState sea prominente.
jasonjwwilliams

Respuestas:


116

La forma de hacerlo es manipular location.hashcuando las actualizaciones de AJAX provocan un cambio de estado en el que le gustaría tener una URL discreta. Por ejemplo, si la URL de tu página es:

http://example.com/

Si una función del lado del cliente ejecutó este código:

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

location.hash = 'foo';

Luego, la URL que se muestra en el navegador se actualizará a:

http://example.com/#foo

Esto permite a los usuarios marcar el estado "foo" de la página y usar el historial del navegador para navegar entre estados.

Con este mecanismo, deberá analizar la parte hash de la URL en el lado del cliente usando JavaScript para crear y mostrar el estado inicial apropiado, ya que los identificadores de fragmentos (la parte después del #) no se envían al servidor.

El complemento de cambio de hash de Ben Alman hace que este último sea muy fácil si está utilizando jQuery.


Parece que tienes razón. Ese es el único enfoque. Esto parece una buena explicación detallada de su consejo: < ajaxpatterns.org/Unique_URLs >
jasonjwwilliams

@buymeasoda Gracias por la edición; No estoy seguro de lo que estaba pensando cuando escribí esa parte.
Dave Ward,

1
Wow, esta respuesta fue muy útil. Aunque los ejemplos de URL son un poco confusos, SO podría reemplazar automáticamente los enlaces con títulos. ¿Qué tal reemplazarlos con algo como example.com y example.com/#foo, para que podamos ver la url completa en texto sin formato.
Neil

44
@Pascal Puede, pero solo en navegadores compatibles con pushState de HTML5. Buena información sobre eso aquí: diveintohtml5.info/history.html
Dave Ward

1
Terminé siendo un gran admirador de history.js para cubrir las bases de compatibilidad del navegador github.com/andreasbernhard/history.js
jocull

18

Mire sitios como book.cakephp.org. Este sitio cambia la URL sin usar el hash y usa AJAX. No estoy seguro de cómo lo hace exactamente, pero he estado tratando de resolverlo. Si alguien lo sabe, hágamelo saber.

También github.com al mirar una navegación dentro de un determinado proyecto.


Me di cuenta de eso con GitHub hace una semana más o menos. ¿Cómo demonios hacen eso? Debe regresar y verificar.
Drew Noakes

16
Parecen estar usando la función javascript pushState (). Esto se suma al historial de su navegador. Mirar dentro; Es bastante interesante y genial.
daniel.wright

Gracias por esto, era exactamente lo que estaba buscando. Me preguntaba cómo lo hizo Github. Al principio pensé que debía estar recargando, pero solo había solicitudes AJAX. En Opera, volvió a cargar la página.
kamranicus

Fb utiliza una técnica similar mientras navega por páginas de diferentes grupos. Tiene una columna de navegación izquierda en la que se mencionan diferentes grupos. Cuando hace clic en un nombre de grupo en particular, la url cambia y solo el contenido del panel de contenido principal cambia junto con la url (sin hash). Entonces, cuando el usuario vuelve a cargar la página, no se redirige a la página de inicio sino a la página de los grupos.
Madeyedexter


11

Esto es similar a lo que dijo Kevin. Puede tener el estado de su cliente como un objeto javascript, y cuando desea guardar el estado, serializa el objeto (usando codificación JSON y base64). Luego puede establecer el fragmento de href en esta cadena.

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

La primera forma tratará el nuevo estado como una nueva ubicación (por lo que el botón Atrás los llevará a la ubicación anterior). Este último no.


¿Hay alguna manera de agregar una entrada al historial de marcadores sin actualizar la página? Establecer la ubicación (como en su primer ejemplo) causará una actualización, ¿no?
Drew Noakes

haciendo document.location.replace también redirigirá el navegador a esa url (solo lo probé en la consola de Chrome)
Omu

3

SWFAddress funciona en proyectos Flash y Javascript y le permite crear URLs marcables (usando el método hash mencionado anteriormente), además de brindarle soporte para los botones de retroceso.

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


3

El método window.location.hash es la forma preferida de hacer las cosas. Para obtener una explicación de cómo hacerlo, Patrones de Ajax: URL únicas .

YUI tiene una implementación de este patrón como un módulo, que incluye soluciones alternativas específicas de IE para que el botón Atrás funcione junto con reescribir la dirección utilizando el hash. Administrador de historial del navegador YUI .

Otros marcos también tienen implementaciones similares. El punto importante es que si desea que el historial funcione junto con la reescritura de la dirección, los diferentes navegadores necesitan diferentes formas de manejarla. (Esto se detalla en el primer artículo del enlace).

IE necesita un hack basado en iframe, donde Firefox producirá doble historial usando el mismo método.


3

Si OP u otros aún están buscando una forma de modificar el historial del navegador para habilitar el estado, usar pushState y replaceState, como lo sugiere IESUS, es la forma 'correcta' de hacerlo ahora. Su principal ventaja sobre location.hash parece ser que crea URL reales, no solo hashes. Si se guarda el historial del navegador con hashes y luego se vuelve a visitar con JavaScript deshabilitado, la aplicación no funcionará, ya que los hash no se envían al servidor. Sin embargo, si se ha utilizado pushState, la ruta completa se enviará al servidor, que luego puede construir para responder adecuadamente a las rutas. Vi un ejemplo en el que se usaban las mismas plantillas de bigote tanto en el servidor como en el lado del cliente. Si el cliente tuviera habilitado JavaScript, obtendría respuestas rápidas al evitar el viaje de ida y vuelta al servidor, pero la aplicación funcionaría perfectamente bien sin el Javascript. Por lo tanto, la aplicación puede degradarse con gracia en ausencia de JavaScript.

Además, creo que hay un marco por ahí, con un nombre como history.js. Para los navegadores que admiten HTML5, usa pushState, pero si el navegador no lo admite, automáticamente recurre al uso de hashes.


2

Compruebe si el usuario está 'en' la página, cuando hace clic en la barra de direcciones, javascript dice que está fuera de la página. Si cambia la barra de url y presiona 'ENTER' con el símbolo '#' dentro de ella, ingresa nuevamente a la página, sin hacer clic en la página manualmente con el cursor del mouse, luego aparecerá un comando de evento keyboad (document.onkeypress) de javascript poder verificar si es enter y activar el javascript para la redirección. Puede verificar si el usuario está EN la página con window.onfocus y verificar si está fuera con window.onblur.

Sí, es posible

;)


Esta es la forma en que me pareció elegante cambiar la página cuando el usuario edita la barra de direcciones con el símbolo #.
Marcelo
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.