Bom tutorial para usar a API de histórico do HTML5 (Pushstate?) [Fechado]


168

Estou pensando em usar a API de histórico do HTML5 para resolver problemas de vínculo profundo com o conteúdo carregado com AJAX, mas estou lutando para sair do papel. Alguém sabe de bons recursos?

Eu quero usar isso, pois parece uma ótima maneira de permitir a possibilidade de aqueles que estão sendo enviados, os links podem não ter o JS ativado. Muitas soluções falham quando alguém com JS envia um link para alguém sem.

Minha pesquisa inicial parece apontar para uma API de histórico no JS e o método pushState.

http://html5demos.com/history

Respostas:


181

Para um ótimo tutorial, a página da Mozilla Developer Network sobre essa funcionalidade é tudo que você precisa: https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history

Infelizmente, a API de histórico do HTML5 é implementada de maneira diferente em todos os navegadores HTML5 (tornando-o inconsistente e com bugs) e não possui substituto para os navegadores HTML4. Felizmente, o History.js fornece compatibilidade cruzada para os navegadores HTML5 (garantindo que todos os navegadores HTML5 funcionem conforme o esperado) e, opcionalmente, fornece um fallback de hash para navegadores HTML4 (incluindo suporte mantido para dados, títulos, funcionalidade pushState e replaceState).

Você pode ler mais sobre o History.js aqui: https://github.com/browserstate/history.js

Para obter um artigo sobre a API de histórico Hashbangs VS Hashes VS HTML5, consulte aqui: https://github.com/browserstate/history.js/wiki/Intelligent-State-Handling


25
Auto-plug descarado. Excelente post e plugin embora. :)
Purag


28

Lembre-se de usar o HTML5 pushstate se um usuário copiar ou adicionar um link direto aos favoritos e visitá-lo novamente; isso será um acesso direto ao servidor, que será 404; portanto, você deve estar pronto para isso, e mesmo uma biblioteca pushstate js não ajudará. vocês. A solução mais fácil é adicionar uma regra de reescrita ao servidor Nginx ou Apache da seguinte maneira:

Apache (no seu vhost, se você estiver usando um):

<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;

Essa é a verdadeira resposta. Isso não aparece em nenhum lugar no wiki / tutoriais do History.js de Balupton, etc. De fato, o History.js não usa hash, então você precisa usar um redirecionamento .htaccess!
adriendenat

13
Idealmente, seu servidor / aplicativo deve responder à rota adequadamente, sem a necessidade de reescrever.
229129 sholsinger

Concordamos, exceto no caso de muitas estruturas JavaScript modernas, como Backbone.js, Spine, Ember, etc. Essas são essencialmente aplicações JavaScript de "uma página". Pode-se encontrar uma solução para servir o modelo de gravação de back-end para SEO, ect, mas, enquanto isso, isso seria necessário.
Mauvis Ledford

*certo. Eu escrevo sobre isso com mais detalhes aqui: readystate4.com/2012/05/17/…
Mauvis Ledford 8/12

6

A especificação do histórico do HTML5 é peculiar.

history.pushState()não despacha um popstateevento ou carrega uma nova página por si só. Era apenas para empurrar o estado para a história. Este é um recurso "desfazer" para aplicativos de página única. Você deve despachar manualmente um popstateevento ou usar history.go()para navegar para o novo estado. A idéia é que um roteador possa ouvir popstateeventos e fazer a navegação por você.

Algumas coisas a serem observadas:

  • history.pushState()e history.replaceState()não despache popstateeventos.
  • history.back(), history.forward()E as costas do navegador e botões de avançar fazer expedição popstateeventos.
  • history.go()e history.go(0)recarregue a página inteira e não envie popstateeventos.
  • history.go(-1)(voltar 1 página) e history.go(1)(avançar 1 página) enviam popstateeventos.

Você pode usar a API do histórico como esta para enviar um novo estado E enviar um evento popstate.

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

Em seguida, ouça popstateeventos com um roteador.


1
Sou apenas eu ou new PopStateEvent(...)parece não funcionar no IE11? Existe uma solução alternativa que alguém conhece?
David Alan Hjelle

Parece que o IE 11 precisa de 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

Você pode experimentar o Davis.js , ele fornece roteamento em seu JavaScript usando pushState quando disponível e sem JavaScript, permite que o código do lado do servidor lide com as solicitações.



2

Você pode dar uma olhada neste plugin jQuery. Eles têm muitos exemplos em seu site. http://www.asual.com/jquery/address/


Novamente, esta solução parece falhar quando o JS está desativado. Acho que a API de histórico tem o poder de trabalhar em conjunto com o modrewrite, para que os links sejam sempre processados ​​em primeira instância pelo servidor, sem a necessidade de redirecionamento da camada JS.
Mild Fuzz

Você está no caminho certo com o modrewrite. A solução de gerenciar a API de histórico e manipular quando o usuário não possui JS são realmente duas coisas separadas. Se você não possui JS, deve manipular o usuário com hrefs padrão e respostas do servidor. A API do histórico pode ser criada como uma espécie de "bom ter" se o navegador do usuário suportar.
Nathan Totten

As amostras Express e State fornecidas com o jQuery Address 1.3 funcionam bastante bem quando o JavaScript está desativado. O segundo usa PHP com mod_rewrite.
Rostislav

Exatamente meu tato. Pretendo construir o site sem JS, adicionar elementos AJAX e usar o histórico para reescrever a URL, preservando os links diretos. Teoricamente, deveria ser um método melhor do que qualquer outro que eu tenha visto, já que o site não dependerá do AJAX, em qualquer estágio #
Mild Fuzz

1
-1, já que o endereço jQuery não é uma porta direta da API de estado do HTML5 - não suporta dados ou títulos e substituiState.
balupton

2

Eu escrevi uma abstração de roteador muito simples sobre o History.js, chamada StateRouter.js . Está nos estágios iniciais de desenvolvimento, mas estou usando-o como a solução de roteamento em um aplicativo de página única que estou escrevendo. Como você, achei o History.js muito difícil de entender, especialmente porque eu sou bastante novo em JavaScript, até entender que você realmente precisa (ou deveria ter) uma abstração de roteamento sobre ela, pois resolve um nível baixo problema.

Este exemplo de código simples deve demonstrar como é usado:

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();

Aqui está um pequeno violino que inventei para demonstrar seu uso.


1
Esse violino não está funcionando para mim no Chrome no Mac. Lança um erro. (Uncaught ReferenceError: staterouter não está definido)
DrewT

@DrewT Obrigado, o violino foi quebrado devido a uma alteração no github.com, mas eu trabalhei com isso.
aknuds1

Sim, trabalhando agora, obrigado pela resposta rápida.
DrewT

1

se o jQuery estiver disponível, você poderá usar o jQuery BBQ


Isso parece falhar com o JS desativado.
Mild Fuzz

isso provavelmente é verdade - não investiguei. Eu acho que você terá esse problema com todas as abordagens baseadas na biblioteca js. Eles são baseados na manipulação da parte de hash do URL.
Sprugman 25/10/10

1
que é o ponto da API Histórico HTML5 - ele não quebrar nada
balupton

2
@MildFuzz O computador parece falhar sem fonte de energia! Eu acho que você tem um erro de ID-10-T ...
Eric Hodonsky

1
Ironicamente, é você que tem misundestood
Mild Fuzz
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.