Como modifico o URL sem recarregar a página?

2377

Existe uma maneira de modificar o URL da página atual sem recarregá-la?

Gostaria de acessar a parte antes do # hash, se possível.

Eu só preciso alterar a parte após o domínio, por isso não estou violando as políticas entre domínios.

 window.location.href = "www.mysite.com/page2.php";  // Sadly this reloads
O Flash
fonte
139
Apenas para facilitar a compreensão da pergunta, é isso que o Facebook faz quando você abre uma foto, por exemplo. A barra de URL muda para apontar DIRETAMENTE para a foto, para que você possa compartilhar o URL sem perder onde está no site. Lembra-se de sites baseados em estruturas na década passada? Você só pôde obter o URL da página inicial, porque apenas os quadros internos estavam mudando. E isso foi terrível.
Spidey
Embora history.pushState()provavelmente seja a resposta certa aqui, nesta situação (dependendo das circunstâncias exatas ...), a possibilidade de usar um redirecionamento do servidor (como usar a diretiva RewriteRule do Apache) é algo que você pode querer considerar, ou pelo menos estar ciente de. Apenas pensei que deveria ser mencionado!
Doin

Respostas:

2033

Agora isso pode ser feito no Chrome, Safari, Firefox 4+ e Internet Explorer 10pp4 +!

Consulte a resposta desta pergunta para obter mais informações: Atualizando a barra de endereços com o novo URL sem hash ou recarregando a página

Exemplo:

 function processAjaxData(response, urlPath){
     document.getElementById("content").innerHTML = response.html;
     document.title = response.pageTitle;
     window.history.pushState({"html":response.html,"pageTitle":response.pageTitle},"", urlPath);
 }

Você pode usar window.onpopstatepara detectar a navegação do botão voltar / avançar:

window.onpopstate = function(e){
    if(e.state){
        document.getElementById("content").innerHTML = e.state.html;
        document.title = e.state.pageTitle;
    }
};

Para uma visão mais aprofundada da manipulação do histórico do navegador, consulte este artigo da MDN .

David Murdoch
fonte
272
Como o facebook faz isso no IE7?
Dominic
57
@CHiRiLo confira history.js, que fornece um substituto para navegadores que não suportam a API de histórico HTML5.
David Murdoch
23
@infensus Se há um sinal # no lugar URL, esse truque já existe há anos ..
Izkata
34
O que significa a parte "pp4 +" de "IE10pp4 +"?
Scott Tesler
34
prévia da plataforma 4
David Murdoch
587

O HTML5 introduziu os métodos history.pushState()e history.replaceState(), que permitem adicionar e modificar entradas do histórico, respectivamente.

window.history.pushState('page2', 'Title', '/page2.php');

Leia mais sobre isso aqui

Vivart
fonte
12
Pode não funcionar file:///por motivos de segurança, por exemplo, Firefox 30. Teste localhostcom python -m SimpleHTTPServer.
Ciro Santilli # 9/14
6
O primeiro parâmetro deve ser um objeto, não apenas uma string.
Alexis Wilke
40
IMO, esta é realmente a melhor resposta. Se tudo o que você deseja fazer é atualizar o URL atual ({}, null, strNewPath) é tudo o que você precisa fazer. Melhor testar primeiro com if (history.pushState) {}
Craig Jacobs
7
você pode simplesmente inserir nulo para os 2 primeiros parâmetros, se não quiser alterá-los. Você também pode usar um URL absoluto para o terceiro parâmetro.
Andrew
3
Seria bom se você colocar mais algumas informações apenas na resposta. Eu não tenho idéia, qual parâmetro 1 faz.
RedClover 24/02
130

Você também pode usar HTML5 replaceState se quiser alterar o URL, mas não deseja adicionar a entrada ao histórico do navegador:

if (window.history.replaceState) {
   //prevents browser from storing history with each change:
   window.history.replaceState(statedata, title, url);
}

Isso 'quebraria' a funcionalidade do botão Voltar. Isso pode ser necessário em alguns casos, como uma galeria de imagens (onde você deseja que o botão voltar retorne à página de índice da galeria, em vez de voltar a cada imagem exibida), fornecendo a cada imagem seu próprio URL exclusivo.

George Filippakos
fonte
110

Aqui está a minha solução (newUrl é o seu novo URL que você deseja substituir pelo atual):

history.pushState({}, null, newUrl);
Haimei
fonte
1
É melhor testar primeiro com if (history.pushState) {} para o caso de um navegador antigo.
Craig Jacobs
Isso não funciona mais: o Firefox é inseguro.
kkatusic
E o usuário pode até definir um marcador com essa abordagem, lindo! Agora posso atualizar o URL na entrada do usuário e ele pode marcar diretamente quaisquer que sejam suas configurações.
codepleb
107

NOTA: Se você estiver trabalhando com um navegador HTML5, deverá ignorar esta resposta. Agora isso é possível, como pode ser visto nas outras respostas.

Não há como modificar o URL no navegador sem recarregar a página. O URL representa qual foi a última página carregada. Se você o alterar ( document.location), ele recarregará a página.

Uma razão óbvia é que você escreve um site www.mysite.comque se parece com uma página de login do banco. Então você altera a barra de URL do navegador para dizer www.mybank.com. O usuário não tem consciência de que realmente está olhando www.mysite.com.

Robin Day
fonte
33
Não quero alterar o domínio, apenas o caminho e o nome do arquivo.
TheFlash 5/05
5
Isso ainda não interrompe os possíveis riscos à segurança, pois o navegador não faz ideia de que domínio / meu site e domínio / outros sites são considerados "seguros" pelo usuário. Talvez a pergunta deva ser: por que você deseja alterar o URL? Para ocultá-lo do usuário, você pode simplesmente executar seu aplicativo dentro de um iframe.
560 Dia de Robin
5
Você pode realmente fazer isso com o Flash. Isso permitirá que você modifique o URL sem fazer uma solicitação. Isso é possível porque o Flash opera fora do navegador, mas com muita força.
22412 Nick Berardi
142
Devo dizer que existem razões perfeitamente válidas para modificar a URL na barra de endereços do lado do cliente. Por exemplo, se você possui uma tabela de dados com paginação, classificação e filtragem, e deseja que essas coisas sejam ativadas pelo Ajax, mas ainda atualize a URL para que o estado atual da página seja marcado como favorito. Entendo os riscos de segurança com a modificação do nome do domínio (phishing etc.), mas por que os navegadores não permitem que apenas a parte da URL à direita do domínio de nível superior seja modificável por meio de script?
Sunday Ironfoot
41
esta resposta não é mais 100% verdadeira. Veja minha resposta para detalhes.
David Murdoch
83
parent.location.hash = "hello";
Martin.
fonte
15
Eu quero mudar o URL, não apenas o hash - #mydata
theflash
42
Alterar o hash pode ser útil no ajax, pois é um tipo de estado sem o uso de cookies, pode ser marcado como favorito e compatível com os botões de retorno do navegador. O Gmail usa isso hoje em dia para torná-lo mais amigável ao navegador.
Matthew Lock
@ Jarvis: qual é a diferença?
barulhento
O rastreamento no lado do servidor não pode ver hashes, a menos que seja enviado explicitamente ao serviço de rastreamento.
RedYetiCo #
isso não é útil se você estiver usando uma estrutura mvc que é roteada no hash, por exemplo, backbone.
#
27

Nos navegadores modernos e no HTML5 , existe um método chamado pushStatena janela history. Isso mudará o URL e o empurrará para o histórico sem carregar a página.

Você pode usá-lo assim, serão necessários 3 parâmetros, 1) objeto de estado 2) título e uma URL):

window.history.pushState({page: "another"}, "another page", "example.html");

Isso mudará o URL, mas não recarregará a página. Além disso, ele não verifica se a página existe; portanto, se você fizer algum código JavaScript que esteja reagindo ao URL, poderá trabalhar com eles dessa maneira.

Também existe o history.replaceState()que faz exatamente a mesma coisa, exceto que ele modificará o histórico atual em vez de criar um novo!

Além disso, você pode criar uma função para verificar se history.pushStateexiste, e continuar com o restante desta forma:

function goTo(page, title, url) {
  if ("undefined" !== typeof history.pushState) {
    history.pushState({page: page}, title, url);
  } else {
    window.location.assign(url);
  }
}

goTo("another page", "example", 'example.html');

Também é possível alterar o #para <HTML5 browsers, que não recarregará a página. É assim que o Angular usa o SPA de acordo com a hashtag ...

Mudar #é bastante fácil, fazendo o seguinte:

window.location.hash = "example";

E você pode detectá-lo assim:

window.onhashchange = function () {
  console.log("#changed", window.location.hash);
}
Alireza
fonte
Faria window.onhashchangee window.onpopstatefaria o mesmo neste caso?
J0ANMM 17/07
Como carregar o conteúdo da página também? Apenas substitui o URL
MD. Atiqur Rahman
Carregue o conteúdo como faria normalmente com o ajax.
AndroidDev 15/09/19
26

O HTML5 replaceState é a resposta, como já mencionado por Vivart e geo1701. No entanto, não é suportado em todos os navegadores / versões. O History.js agrupa os recursos do estado HTML5 e fornece suporte adicional aos navegadores HTML4.

Thomas Stjernegaard Jeppesen
fonte
24

Antes do HTML5, podemos usar:

parent.location.hash = "hello";

e:

window.location.replace("http:www.example.com");

Este método recarregará sua página, mas o HTML5 introduziu o history.pushState(page, caption, replace_url)que não deve recarregar sua página.

Brilho
fonte
2
O problema history.pushState(..)é que, se você deseja redirecionar para outro domínio, a política entre domínios entra em vigor. Enquanto com o window.location.replace(..)redirecionamento para outro domínio é possível.
OSWorX
23

Se o que você está tentando fazer é permitir que os usuários adicionem aos favoritos / compartilhem páginas, e você não precisa que ele seja exatamente o URL certo, e não está usando âncoras de hash para mais nada, pode fazer isso em duas partes; você usa o location.hash discutido acima e, em seguida, implementa uma verificação na página inicial, para procurar um URL com uma âncora de hash e redirecioná-lo para o resultado subsequente.

Por exemplo:

1) O usuário está ativado www.site.com/section/page/4

2) O usuário executa alguma ação que altera o URL para www.site.com/#/section/page/6 (com o hash). Digamos que você carregou o conteúdo correto da página 6 na página, portanto, além do hash, o usuário não fica muito perturbado.

3) O usuário passa esse URL para outra pessoa ou o adiciona aos favoritos

4) Outra pessoa, ou o mesmo usuário posteriormente, vai para www.site.com/#/section/page/6

5) O código no www.site.com/redireciona o usuário para www.site.com/section/page/6, usando algo como isto:

if (window.location.hash.length > 0){ 
   window.location = window.location.hash.substring(1);
}

Espero que faça sentido! É uma abordagem útil para algumas situações.

Jeremy Warne
fonte
17

Abaixo está a função de alterar o URL sem recarregar a página. É suportado apenas para HTML5.

  function ChangeUrl(page, url) {
        if (typeof (history.pushState) != "undefined") {
            var obj = {Page: page, Url: url};
            history.pushState(obj, obj.Page, obj.Url);
        } else {
            window.location.href = "homePage";
            // alert("Browser does not support HTML5.");
        }
    }

  ChangeUrl('Page1', 'homePage');
Suraj
fonte
2
@ Verde, página é um título curto para o estado para o qual você está se movendo. O Firefox atualmente ignora esse parâmetro, embora possa usá-lo no futuro. Passar a string vazia aqui deve ser seguro contra futuras alterações no método. De: developer.mozilla.org/pt-BR/docs/Web/API/…
Snook
13

Quaisquer alterações no local ( window.locationoudocument.location ) causarão uma solicitação nesse novo URL, se você não estiver apenas alterando o fragmento do URL. Se você alterar o URL, altere o URL.

Use técnicas de reescrita de URL do lado do servidor, como o mod_rewrite do Apache, se você não gostar dos URLs que está usando no momento.

quiabo
fonte
Posso usar "location.pathname" ??
TheFlash 5/05
3
Não, alterar esse atributo também causará uma solicitação.
Gumbo
11

Você pode adicionar tags de âncora. Eu uso isso no meu site para poder acompanhar com o Google Analytics o que as pessoas estão visitando na página.

Acabei de adicionar uma marca de âncora e, em seguida, a parte da página que desejo rastrear:

var trackCode = "/#" + urlencode($("myDiv").text());
window.location.href = "http://www.piano-chords.net" + trackCode;
pageTracker._trackPageview(trackCode);
Nate
fonte
9

Conforme apontado por Thomas Stjernegaard Jeppesen, você pode usar o History.js para modificar os parâmetros de URL enquanto o usuário navega pelos aplicativos e links do Ajax.

Quase um ano se passou desde essa resposta, e o History.js cresceu e se tornou mais estável e com vários navegadores. Agora, ele pode ser usado para gerenciar estados de histórico em navegadores compatíveis com HTML5 e em muitos navegadores apenas HTML4. Nesta demonstração, você pode ver um exemplo de como funciona (além de poder experimentar suas funcionalidades e limites.

Se você precisar de alguma ajuda sobre como usar e implementar esta biblioteca, sugiro que você dê uma olhada no código fonte da página de demonstração: você verá que é muito fácil de fazer.

Por fim, para obter uma explicação abrangente sobre quais podem ser os problemas sobre o uso de hashes (e hashbangs), confira este link de Benjamin Lupton.

Erenor Paz
fonte
8

Usar history.pushState() partir da API de histórico do HTML 5.

Consulte a API de histórico do HTML5 para obter mais detalhes.

Prathamesh Rasam
fonte
7

Você pode usar esta função bonita e simples para fazê-lo em qualquer lugar do seu aplicativo.

function changeurl(url, title) {
    var new_url = '/' + url;
    window.history.pushState('data', 'Title', new_url);
    document.title = title;
}

Você não pode apenas editar o URL, mas também pode atualizar o título.

Muito útil a todos.

Dheeraj Thedijje
fonte
1
Funciona como um encanto, mesmo para âncoraswindow.history.pushState('data', 'Title', '#new_location');
BIOHAZARD