exemplo history.replaceState ()?

127

Qualquer um pode dar um exemplo de trabalho para history.replaceState? Isto é o que o w3.org diz:

history . replaceState(data, title [, url ] )

Atualiza a entrada atual no histórico da sessão para ter os dados, o título e, se fornecidos e não nulos, o URL.

Atualizar:

Isso funciona perfeitamente:

history.replaceState( {} , 'foo', '/foo' );

O URL está mudando, mas o título não está mudando. Isso é um bug ou estou faltando alguma coisa? Testado no Chrome mais recente.

Serjas
fonte
3
Geralmente, não envio bibliotecas de complementos para perguntas sobre JavaScript, mas neste caso, farei uma exceção. A biblioteca History.js é um pequeno calço que limpa muitos comportamentos estranhos na API do History nos navegadores modernos. Ele ainda fornece suporte opcional para versões antigas do IE.
Pointy
2
MDN tem um bom writeup em Manipulando o histórico do navegador
sachleen
@Pointy history.js funciona muito bem. Eu atualizei o código na minha pergunta. No meu problema é que eu não posso voltar para a página anterior com o botão do navegador de volta
Serjas
3
De acordo com a Mozilla , o titleparâmetro não é realmente usado.
Rocket Hazmat
3
A primeira resposta realmente não deve ser a resposta aceita, dado que a pergunta pede um replaceStateexemplo, e a resposta aceita não é de forma alguma um replaceStateexemplo.
precisa saber é o seguinte

Respostas:

68

Na verdade, isso é um bug, embora intencional por 2 anos. O problema está em algumas especificações pouco claras e na complexidade de quando document.titlee para trás / para a frente estão envolvidos.

Veja a referência de bug no Webkit e Mozilla . Também o Opera, sobre a introdução da API History, disse que não estava usando o parâmetro title e provavelmente ainda não usa.

Atualmente, o segundo argumento de pushState e replaceState - o título da entrada do histórico - não é usado na implementação do Opera, mas pode ser um dia.

Solução potencial

A única maneira que vejo é alterar o elemento title e usar o pushState:

document.getElementsByTagName('title')[0].innerHTML = 'bar';
window.history.pushState( {} , 'bar', '/bar' );
Sev
fonte
Para usuários jquery .. tente $ ("title"). Html (_title);
precisa saber é o seguinte
3
isso pode resultar em usuários que precisam "clicar duas vezes" no botão voltar, dependendo de como você implementa isso. Uma solução mais simples pode ser continuar usando replaceState()e simplesmente definir o título do documento manualmentedocument.title = "title"
newshorts
38

Aqui está um exemplo mínimo e artificial.

console.log( window.location.href );  // whatever your current location href is
window.history.replaceState( {} , 'foo', '/foo' );
console.log( window.location.href );  // oh, hey, it replaced the path with /foo

Há mais, replaceState()mas não sei exatamente o que você quer fazer com isso.

Trott
fonte
2
url está mudando, mas o título não está mudando .. testado com o mais recente chrome @trott
Serjas 11/11
6
@Serjas O titleparâmetro in replaceState()é, dentro do meu conhecimento, ignorado em todos os navegadores.
Trott 02/02
10

history.pushStatecoloca o estado da página atual na pilha do histórico e altera o URL na barra de endereço. Então, quando você voltar, esse estado (o objeto que você passou) será retornado para você.

Atualmente, isso é tudo o que faz. Qualquer outra ação da página, como exibir a nova página ou alterar o título da página, deve ser realizada por você.

A especificação do W3C que você vincula é apenas um rascunho e o navegador pode implementá-lo de maneira diferente. O Firefox , por exemplo, ignora titlecompletamente o parâmetro.

Aqui está um exemplo simples do pushStateque eu uso no meu site.

(function($){
    // Use AJAX to load the page, and change the title
    function loadPage(sel, p){
        $(sel).load(p + ' #content', function(){
            document.title = $('#pageData').data('title');
        });
    }

    // When a link is clicked, use AJAX to load that page
    // but use pushState to change the URL bar
    $(document).on('click', 'a', function(e){
        e.preventDefault();
        history.pushState({page: this.href}, '', this.href);
        loadPage('#frontPage', this.href);
    });

    // This event is triggered when you visit a page in the history
    // like when yu push the "back" button
    $(window).on('popstate', function(e){
        loadPage('#frontPage', location.pathname);
        console.log(e.originalEvent.state);
    });
}(jQuery));
Foguete Hazmat
fonte
29
Por que a resposta aceita explica "pushState" em vez de "replaceState"?
Giwrgos Tsopanoglou
1
@ GiwrgosTsopanoglou: Eu respondi isso há um ano, então não sei por que :-P De qualquer forma, replaceStatealtera o estado da página atual. Permite alterar o objeto de estado e o URL do estado atual da página.
Rocket Hazmat
2
Era apenas estranho que eu estava procurando informações sobre replaceState e acabei de ler sobre pushState: P
Giwrgos Tsopanoglou
6

Olhe para o exemplo

window.history.replaceState({
    foo: 'bar'
}, 'Nice URL Title', '/nice_url');

window.onpopstate = function (e) {
    if (typeof e.state == "object" && e.state.foo == "bar") {
        alert("Blah blah blah");
    }
};

window.history.go(-1);

e pesquisa location.hash;

avalkab
fonte
2

De acordo com o documento MDN History,
diz-se claramente que o segundo argumento é para o futuro usado e não por enquanto. Você está certo de que o segundo argumento trata do título da página da web, mas atualmente é ignorado por todos os principais navegadores.

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. Como alternativa, você pode passar um título curto para o estado para o qual está se mudando.

Munir Khakhi
fonte
O segundo argumento não se refere ao título da página da web - o documento MDN que você vinculou diz "passe um título curto para o estado para o qual você está se movendo". . Isso concorda com a documentação da interface do histórico do W3C , que diz "Coloca os dados fornecidos no histórico da sessão, com o título especificado" . Os dados nessa frase são os dados do estado ; portanto, novamente o título se refere ao estado (dados).
Stephen P
1

Eu realmente queria responder à resposta de @ Sev.

Sev está certo, há um erro dentro do window.history.replaceState

Para corrigir isso, basta reescrever o construtor para definir o título manualmente.

var replaceState_tmp = window.history.replaceState.constructor;
window.history.replaceState.constructor = function(obj, title, url){
    var title_ = document.getElementsByTagName('title')[0];
    if(title_ != undefined){
        title_.innerHTML = title;
    }else{
        var title__ = document.createElement('title');
        title__.innerHTML = title;
        var head_ = document.getElementsByTagName('head')[0];
        if(head_ != undefined){
            head_.appendChild(title__);
        }else{
            var head__ = document.createElement('head');
            document.documentElement.appendChild(head__);
            head__.appendChild(title__);
        }
    }
    replaceState_tmp(obj,title, url);
}
O INCRÍVEL
fonte
2
Não faça isso. Substituindo funções padrão é reaaaally estilo ruim
René Roth
3
o que mais você sugere quando precisa desse bug corrigido?
Glenn Plas
@GlennPlas abrir um PR contra o repo reagir :)
zero_cool
0

Suponha que https://www.mozilla.org/foo.html execute o seguinte JavaScript:

const stateObj = { foo: 'bar' };

history.pushState(stateObj, '', 'bar.html');

Isso fará com que a barra de URL seja exibida https://www.mozilla.org/bar2.html , mas não fará com que o navegador carregue bar2.html ou verifique se a barra2.html existe.

acinzentado
fonte