Modificar URL da barra de endereço no aplicativo AJAX para corresponder ao estado atual

166

Estou escrevendo um aplicativo AJAX, mas, à medida que o usuário passa pelo aplicativo, eu gostaria que o URL na barra de endereços fosse atualizado, apesar da falta de recargas de página. Basicamente, gostaria que eles pudessem marcar os favoritos a qualquer momento e, assim, retornar ao estado atual.

Como as pessoas lidam com a manutenção do RESTfulness nos aplicativos AJAX?

jasonjwwilliams
fonte
2
É usado para manter o estado de seus aplicativos, mas não tem nada a ver com "RESTfulness".
Mohamed
29
window.history.pushState(null,'hi','page1?id=32')
Omu
3
a resposta aceita foi escrita há 5 anos e, enquanto isso, obtivemos window.history.pushState, exatamente como @Omu disse. o location.hash trouxe vários problemas e é melhor evitá-lo.
pcarvalho 21/09
Editei a resposta para destacar a abordagem pushState.
jasonjwwilliams

Respostas:

116

A maneira de fazer isso é manipular location.hashquando as atualizações do AJAX resultam em uma alteração de estado que você deseja que tenha um URL discreto. Por exemplo, se o URL da sua página for:

http://example.com/

Se uma função do lado do cliente executou este código:

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

location.hash = 'foo';

Em seguida, o URL exibido no navegador será atualizado para:

http://example.com/#foo

Isso permite aos usuários marcar o estado "foo" da página e usar o histórico do navegador para navegar entre os estados.

Com esse mecanismo, você precisará analisar a parte de hash da URL no lado do cliente usando JavaScript para criar e exibir o estado inicial apropriado, pois os identificadores de fragmento (a parte após o #) não são enviados para o servidor.

O plugin hashchange de Ben Alman torna este último fácil, se você estiver usando o jQuery.

Dave Ward
fonte
Parece que você está certo. Essa é a única abordagem. Parece uma boa explicação detalhada de seus conselhos: < ajaxpatterns.org/Unique_URLs >
jasonjwwilliams
@buymeasoda Obrigado pela edição; Não tenho certeza do que estava pensando quando escrevi essa parte.
Dave Ward
1
Uau, esta resposta foi muito útil. Embora os exemplos de URL sejam um pouco confusos, o SO pode substituir automaticamente os links por títulos. Que tal substituir aqueles por algo como example.com e example.com/#foo, para que possamos ver o URL inteiro em texto sem formatação.
21411 Neil
4
@ Pascal Você pode, mas apenas em navegadores que suportam o pushState do HTML5. Boas informações sobre isso aqui: diveintohtml5.info/history.html
Dave Ward
1
Acabei sendo um grande fã do history.js para cobrir as bases de compatibilidade do navegador github.com/andreasbernhard/history.js
jocull
18

Olhe sites como book.cakephp.org. Este site altera a URL sem usar o hash e usar AJAX. Não tenho certeza de como exatamente isso acontece, mas tenho tentado descobrir. Se alguém souber, me avise.

Também github.com ao olhar para uma navegação em um determinado projeto.

daniel.wright
fonte
Percebi isso com o GitHub há mais ou menos uma semana. Como diabos eles fazem isso? Deve voltar e verificar.
Drew Noakes
16
Eles parecem estar usando a função javascript pushState (). Isso adiciona ao histórico do seu navegador. Olhe para ele; é bem interessante e legal.
Daniel.wright
Obrigado por isso, era exatamente o que eu estava procurando. Eu me perguntava como o github fazia isso. No começo, pensei que deveria estar recarregando, mas havia apenas solicitações AJAX. No Opera, ele recarregou a página.
Kamranicus
Técnica semelhante é usada pelo fb enquanto navega pelas páginas de diferentes grupos. Você tem uma coluna de navegação esquerda na qual diferentes grupos são mencionados. Quando você clica em um nome de grupo específico, o URL é alterado e apenas o conteúdo do painel de conteúdo principal é alterado junto com o URL (sem hash). Portanto, quando o usuário recarrega a página, ele não é redirecionado para a página inicial, mas para a página dos grupos.
Madeyedexter
11

Isso é semelhante ao que Kevin disse. Você pode ter o estado do cliente como um objeto javascript e, quando desejar salvar o estado, serialize o objeto (usando a codificação JSON e base64). Você pode definir o fragmento do href para essa sequência.

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

A primeira maneira tratará o novo estado como um novo local (para que o botão Voltar os leve ao local anterior). O último não.


fonte
Existe uma maneira de adicionar uma entrada ao histórico de favoritos sem atualizar a página? Definir a localização (como no seu primeiro exemplo) causará uma atualização, não é?
Desenhou Noakes
fazendo document.location.replace também irá redirecionar o navegador para que url (apenas tentei em cromo console)
Omu
3

O SWFAddress funciona em projetos Flash e Javascript e permite criar URLs que podem ser marcados como favoritos (usando o método hash mencionado acima), além de oferecer suporte ao botão voltar.

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


fonte
3

O método window.location.hash é a maneira preferida de fazer as coisas. Para obter uma explicação de como fazer isso, Padrões Ajax - URLs exclusivos .

A YUI possui uma implementação desse padrão como um módulo, que inclui soluções alternativas específicas do IE para fazer com que o botão voltar funcione, além de reescrever o endereço usando o hash. Gerenciador de histórico do navegador YUI .

Outras estruturas também têm implementações semelhantes. O ponto importante é que se você deseja que o histórico funcione junto com a reescrita do endereço, os diferentes navegadores precisam de maneiras diferentes de lidar com ele. (Isso está detalhado no primeiro artigo do link.)

O IE precisa de um hack baseado em iframe, onde o Firefox produzirá um histórico duplo usando o mesmo método.

Drew Noakes
fonte
3

Se o OP ou outros ainda estiverem procurando uma maneira de modificar o histórico do navegador para ativar o estado, usar pushState e replaceState, conforme sugerido pelo IESUS, é a maneira 'certa' de fazê-lo agora. É a principal vantagem sobre a localização. Parece que ele cria URLs reais, não apenas hashes. Se o histórico do navegador usando hashes for salvo e revisado novamente com o javascript desativado, o aplicativo não funcionará, pois os hashes não são enviados ao servidor. No entanto, se o pushState tiver sido usado, a rota inteira será enviada ao servidor, que você poderá criar para responder adequadamente às rotas. Eu vi um exemplo em que os mesmos modelos de bigode foram usados ​​no servidor e no lado do cliente. Se o cliente tivesse o javascript ativado, ele obteria respostas rápidas, evitando a ida e volta ao servidor, mas o aplicativo funcionaria perfeitamente sem o javascript. Assim, o aplicativo pode degradar-se normalmente na ausência de javascript.

Além disso, acredito que exista alguma estrutura por aí, com um nome como history.js. Para navegadores que suportam HTML5, ele usa pushState, mas se o navegador não suportar, ele automaticamente volta a usar hashes.

Neil
fonte
2

Verifique se o usuário está 'na' página, quando você clica na barra de URL, o javascript diz que você está fora da página. Se você alterar a barra de URL e pressionar 'ENTER' com o símbolo '#' dentro dela, entrará na página novamente, sem clicar na página manualmente com o cursor do mouse, um comando de evento keyboad (document.onkeypress) do javascript poderá verificar se está inserido e ativo o javascript para redirecionamento. Você pode verificar se o usuário está NA página com window.onfocus e se ele está fora com window.onblur.

Sim, é possível.

;)

Marcelo
fonte
Foi assim que achei elegante alterar a página quando o usuário editar a barra de URL com o símbolo #.
Marcelo