2010-10-25 12 views
168

Estoy buscando utilizar la API de historial de HTML5 para resolver problemas de enlaces profundos con contenido cargado AJAX, pero estoy luchando para despegar. ¿Alguien sabe de algún buen recurso?Buen tutorial para utilizar la API de historial de HTML5 (Pushstate?)

Quiero usar esto, ya que parece una gran manera de permitir la posibilidad de que los que se envían los enlaces no pueden tener activado JS. Muchas soluciones fallan cuando alguien con JS envía un enlace a alguien que no tiene.

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

http://html5demos.com/history

Respuesta

179

Para un gran tutorial de la página de red de desarrolladores de Mozilla en esta funcionalidad es todo lo que necesita: https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history

Por desgracia, la API HTML5 Historia se implementa de manera diferente en todos los navegadores HTML5 (por lo que es incoherente y con errores) y no tiene ninguna alternativa para los navegadores HTML4. Afortunadamente, History.js proporciona compatibilidad cruzada para los navegadores HTML5 (asegurando que todos los navegadores HTML5 funcionen como se espera) y opcionalmente ofrece un hash-back para navegadores HTML4 (incluyendo soporte mantenido para datos, títulos, pushState y funcionalidad replaceState).

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

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

+25

Autoadhesivo desvergonzado. Excelente publicación y plugin sin embargo. :) – Purag

2

es posible que desee echar un vistazo a este plugin jQuery. Ellos tienen muchos ejemplos en su sitio. http://www.asual.com/jquery/address/

+0

De nuevo, esta solución parece fallar cuando JS está apagado. Creo que la API de historial tiene el poder de trabajar en conjunto con modrewrite para que los enlaces siempre sean procesados ​​en primera instancia por el servidor, sin necesidad de redirección desde la capa JS. –

+0

Estás en el camino correcto con el modrewrite. La solución de administrar la API de historial y su manejo cuando el usuario no tiene JS son en realidad 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 construirse como algo "agradable de tener" si el navegador del usuario lo admite. –

+0

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

1

si jQuery está disponible, puede utilizar jQuery BBQ

+0

Esto parece fallar con JS apagado. –

+0

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

+1

ese es el objetivo de la API de historial de HTML5: [no rompe nada] (https://github.com/balupton/history.js/wiki/Intelligent-State-Handling) – balupton

4

Usted podría intentar Davis.js, que le da el enrutamiento en su JavaScript usando pushState cuando esté disponible y sin JavaScript, permite que su código del servidor maneje las solicitudes.

24

Tenga en cuenta durante el uso de HTML5 pushState si un usuario copia o marcadores en un enlace y visitas profunda de nuevo, a continuación, ese será un golpe directo al servidor que será 404, por lo que debe estar preparado para ello e incluso una biblioteca js de pushstate no lo ayudará. La solución más sencilla es añadir una regla de reescritura a su servidor Apache o Nginx así:

Apache (en su host 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; 
+0

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

+13

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

+0

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

2

He escrito una abstracción de enrutador muy simple sobre History.js, llamado 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, he encontrado 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 además de resolver un bajo nivel problema.

Este sencillo ejemplo de código debe 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(); 

He aquí una pequeña fiddle He inventé el fin de demostrar su uso.

+1

Este violín no funciona para mí en Chrome en Mac. Lanza un error. (Unbeught ReferenceError: staterouter no está definido) – DrewT

+0

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

+0

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

4

El HTML5 history spec es peculiar.

history.pushState() no envía un evento popstate o carga una página nueva por sí mismo. Solo pretendía llevar el estado a la historia. Esta es una función de "deshacer" para aplicaciones de una sola página. Debe enviar manualmente un evento popstate o usar history.go() para navegar al nuevo estado. La idea es que un enrutador pueda escuchar los eventos popstate y hacer la navegación por usted.

Algunas cosas a tener en cuenta:

  • history.pushState() y history.replaceState() no distribuyen popstate eventos.
  • history.back(), history.forward(), y los botones hacia atrás y hacia adelante del navegador envían popstate eventos.
  • history.go() y history.go(0) hacer una recarga de página completa y no despachar popstate eventos.
  • history.go(-1) (volver 1 página) y history.go(1) (reenviar 1 página) enviar popstate eventos.

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

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

luego espera que popstate eventos con un router.

+1

¿Soy solo yo o el 'nuevo PopStateEvent (...)' parece no funcionar en IE11? ¿Hay alguna solución que alguien sepa? –

+0

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); ' –

Cuestiones relacionadas