Buen tutorial para usar la API de historial HTML5 (¿Pushstate?) [Cerrado]


168

Estoy buscando usar la API de historial HTML5 para resolver problemas de enlaces profundos con contenido cargado AJAX, pero estoy luchando por despegar. ¿Alguien sabe de algún buen recurso?

Quiero usar esto, ya que parece una excelente manera de permitir la posibilidad de que los que se envían los enlaces no tengan JS activado. Muchas soluciones fallan cuando alguien con JS envía un enlace a alguien sin él.

Mi investigación inicial parece apuntar a una API de Historia dentro de JS y al método pushState.

http://html5demos.com/history

Respuestas:


181

Para un gran tutorial, la página de Mozilla Developer Network sobre esta funcionalidad es todo lo que necesitará: https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history

Desafortunadamente, la API de historial HTML5 se implementa de manera diferente en todos los navegadores HTML5 (lo que lo hace inconsistente y con errores) y no tiene respaldo para los navegadores HTML4. Afortunadamente, History.js proporciona compatibilidad cruzada para los navegadores HTML5 (lo que garantiza que todos los navegadores HTML5 funcionen como se esperaba) y opcionalmente proporciona un hash-fallback para los navegadores HTML4 (incluido el soporte mantenido para la funcionalidad de datos, títulos, pushState y replaceState).

Puede leer más sobre History.js aquí: https://github.com/browserstate/history.js

Para ver un artículo sobre Hashbangs VS Hashes VS HTML5 History API, consulte aquí: https://github.com/browserstate/history.js/wiki/Intelligent-State-Handling


25
Autoenchufe descarado. Excelente publicación y complemento sin embargo. :)
Purag


28

Tenga en cuenta al usar HTML5 pushstate si un usuario copia o marca un enlace profundo y lo vuelve a visitar, entonces será un éxito directo del servidor que será 404, por lo que debe estar listo para ello e incluso una biblioteca pushstate js no ayudará tú. La solución más fácil es agregar una regla de reescritura a su servidor Nginx o Apache de la siguiente manera:

Apache (en su servidor virtual si está usando uno):

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /
    RewriteRule ^index\.html$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.html [L]
 </IfModule>

Nginx

rewrite ^(.+)$ /index.html last;

Esa es la verdadera respuesta. Esto no está en ninguna parte del wiki / tutoriales History.js de Balupton, etc. De hecho, History.js no usa hash, por lo que debe usar una redirección .htaccess.
adriendenat

13
Idealmente, su servidor / aplicación debería responder a la ruta de manera adecuada sin la necesidad de esta reescritura.
sholsinger

De acuerdo, excepto en el caso de muchos frameworks JavaScript modernos como Backbone.js, Spine, Ember, etc. Estas son todas aplicaciones esencialmente JavaScript de "una página". Se podría encontrar una solución para servir la plantilla de backend de escritura para SEO, etc., pero mientras tanto esto sería necesario.
Mauvis Ledford

*Derecha. Escribo sobre esto con más detalle aquí: readystate4.com/2012/05/17/…
Mauvis Ledford

6

La especificación del historial HTML5 es peculiar.

history.pushState()no despacha un popstateevento ni carga una nueva página por sí mismo. Solo estaba destinado a empujar al estado a la historia. Esta es una función de "deshacer" para aplicaciones de una sola página. Debe despachar manualmente un popstateevento o utilizarlo history.go()para navegar al nuevo estado. La idea es que un enrutador pueda escucharpopstate eventos y hacer la navegación por usted.

Algunas cosas a tener en cuenta:

  • history.pushState()y history.replaceState()no despacharpopstate eventos.
  • history.back(), history.forward()y los botones de avance y retroceso del navegador se despachanpopstate de eventos.
  • history.go()y history.go(0)hacer una recarga de página completa y no enviarpopstate eventos.
  • history.go(-1)(atrás 1 página) y history.go(1)(adelante 1 página) hacen popstateeventos de despacho .

Puede usar la API de historial de esta manera para impulsar un nuevo estado Y enviar un evento popstate.

history.pushState({message:'New State!'}, 'New Title', '/link'); window.dispatchEvent(new PopStateEvent('popstate', { bubbles: false, cancelable: false, state: history.state }));

Luego escuche los popstateeventos con un enrutador.


1
¿Soy solo yo o new PopStateEvent(...)parece que no funciona en IE11? ¿Hay alguna solución que alguien sepa?
David Alan Hjelle

Parece que IE 11 necesita algo como: var pop_state_event = document.createEvent('Event'); pop_state_event.initEvent('popstate', true, true); window.dispatchEvent(pop_state_event);
David Alan Hjelle

4

Puede probar Davis.js , le brinda enrutamiento en su JavaScript utilizando pushState cuando está disponible y sin JavaScript permite que el código del lado del servidor maneje las solicitudes.



2

Es posible que desee echar un vistazo a este complemento jQuery. Tienen muchos ejemplos en su sitio. http://www.asual.com/jquery/address/


Nuevamente, esta solución parece fallar cuando JS está apagado. Creo que la API de historia tiene el poder de trabajar junto con modrewrite para que el servidor siempre procese los enlaces en primera instancia, sin necesidad de redireccionar desde la capa JS.
Mild Fuzz

Estás en el camino correcto con la modrewrite. La solución de administrar la API de historial y el manejo cuando el usuario no tiene JS son realmente dos cosas separadas. Si no tiene JS, debe manejar al usuario con hrefs estándar y respuestas del servidor. La API de historial podría compilarse como algo "agradable de tener" si el navegador del usuario lo admite.
Nathan Totten

Tanto las muestras Express como State que se envían con jQuery Address 1.3 funcionan bastante bien cuando JavaScript está deshabilitado. El segundo usa PHP con mod_rewrite.
Rostislav

Exactamente mi tacto. Tengo la intención de construir el sitio sin JS, agregar elementos AJAX y luego usar el historial para reescribir la URL, preservando los enlaces profundos. Teóricamente, debería ser un método mejor que cualquiera de los que he visto, ya que el sitio no dependerá de AJAX, en ninguna etapa
Mild Fuzz

1
-1 como jQuery Address no es un puerto directo de la API de estado HTML5: no admite datos o títulos, y reemplaza State.
Balupton

2

He escrito una abstracción de enrutador muy simple sobre History.js, llamada StateRouter.js . Está en las primeras etapas de desarrollo, pero lo estoy usando como la solución de enrutamiento en una aplicación de una sola página que estoy escribiendo. Al igual que usted, encontré que History.js es muy difícil de entender, especialmente porque soy bastante nuevo en JavaScript, hasta que entendí que realmente necesita (o debería tener) una abstracción de enrutamiento, ya que resuelve un nivel bajo problema.

Este código de ejemplo simple debería demostrar cómo se usa:

var router = new staterouter.Router();
// Configure routes
router
  .route('/', getHome)
  .route('/persons', getPersons)
  .route('/persons/:id', getPerson);
// Perform routing of the current state
router.perform();

Aquí hay un pequeño violín que he inventado para demostrar su uso.


1
Este violín no me funciona en Chrome para Mac. Lanza un error. (Error de referencia no capturado: staterouter no está definido)
DrewT

@DrewT Gracias, el violín se rompió debido a un cambio en github.com, pero he solucionado el problema.
aknuds1

Sí, trabajando ahora, gracias por la rápida respuesta.
DrewT

1

Si jQuery está disponible, puede usar jQuery BBQ


Esto parece fallar con JS apagado.
Mild Fuzz

eso es probablemente cierto, no lo he investigado. Creo que tendrá ese problema con todos los enfoques basados ​​en la biblioteca js. Se basan en la manipulación de la parte hash de la url.
Sprugman

1
que es el punto de la API de HTML5 Historia - que no se rompe nada
balupton

2
¡La computadora @MildFuzz parece fallar sin fuente de energía! Creo que tiene un error ID-10-T ...
Eric Hodonsky

1
Irónicamente, eres tú quien ha entendido mal
Mild Fuzz
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.