Exemple avec history.replaceState ()?

127

Quelqu'un peut-il donner un exemple de travail pour history.replaceState? Voici ce que dit w3.org :

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

Met à jour l'entrée actuelle dans l'historique de la session pour avoir les données, le titre et, s'il est fourni et non nul, l'URL.

Mettre à jour:

Cela fonctionne parfaitement:

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

L'URL change, mais le titre ne change pas. Est-ce un bug ou est-ce que je manque quelque chose? Testé sur le dernier Chrome.

Serjas
la source
3
Je ne pousse généralement pas les bibliothèques complémentaires pour les questions JavaScript, mais dans ce cas, je ferai une exception. La bibliothèque History.js est un petit shim qui nettoie beaucoup de mauvais comportements bizarres dans l'API History sur les navigateurs modernes. Il fournit même un support optionnel pour les anciennes versions d'IE.
Pointy du
2
MDN a un très bon article sur la manipulation de l'historique du navigateur
sachleen
@Pointy history.js fonctionne très bien. J'ai mis à jour le code de ma question. Non, mon problème est que je ne peux pas revenir à la page précédente avec le bouton de retour du navigateur
Serjas
3
Selon Mozilla , le titleparamètre n'est pas réellement utilisé.
Rocket Hazmat
3
La première réponse ne devrait vraiment pas être la réponse acceptée, étant donné que la question demande un replaceStateexemple, et la réponse acceptée n'est en aucun cas un replaceStateexemple.
CorayJeu

Réponses:

68

En effet c'est un bug, bien que intentionnel depuis maintenant 2 ans. Le problème réside dans certaines spécifications peu claires et la complexité du moment document.titleet de l'arrière / de l'avant.

Voir la référence de bogue sur Webkit et Mozilla . Opera, lors de l'introduction de l'API History, a également déclaré qu'il n'utilisait pas le paramètre title et qu'il ne le fait probablement toujours pas.

Actuellement, le 2ème argument de pushState et replaceState - le titre de l'entrée d'historique - n'est pas utilisé dans l'implémentation d'Opera, mais peut l'être un jour.

Solution potentielle

La seule façon que je vois est de modifier l'élément title et d'utiliser à la place pushState:

document.getElementsByTagName('title')[0].innerHTML = 'bar';
window.history.pushState( {} , 'bar', '/bar' );
Sev
la source
Pour les utilisateurs de jquery .. essayez $ ("title"). Html (_title);
suraj jain le
3
cela peut amener les utilisateurs à "double-cliquer" sur le bouton de retour en fonction de la façon dont vous implémentez cela. Une solution plus simple pourrait être de continuer à utiliser replaceState()et de définir simplement le titre du document manuellementdocument.title = "title"
newshorts
38

Voici un exemple minimal et artificiel.

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

Il y a plus à faire replaceState()mais je ne sais pas exactement ce que vous voulez en faire.

Trott
la source
2
l'url change, mais le titre ne change pas .. testé avec le dernier chrome @trott
Serjas
6
@Serjas Le titleparamètre dans replaceState()est, à ma connaissance, ignoré dans tous les navigateurs.
Trott le
10

history.pushStatepousse l' état actuel de la page sur la pile d'historique et modifie l'URL dans la barre d'adresse. Ainsi, lorsque vous revenez en arrière, cet état (l'objet que vous avez passé) vous est retourné.

Actuellement, c'est tout ce qu'il fait. Toute autre action de page, telle que l'affichage de la nouvelle page ou la modification du titre de la page, doit être effectuée par vous.

La spécification W3C que vous liez n'est qu'un brouillon et le navigateur peut l'implémenter différemment. Firefox , par exemple, ignore titlecomplètement le paramètre.

Voici un exemple simple pushStateque j'utilise sur mon site Web.

(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));
Fusée Hazmat
la source
29
Pourquoi la réponse acceptée explique "pushState" au lieu de "replaceState"?
Giwrgos Tsopanoglou
1
@GiwrgosTsopanoglou: J'ai répondu à cela il y a un an, donc je ne sais pas pourquoi :-P Quoi qu'il en soit, replaceStatechange l'état actuel de la page. Il vous permet de modifier l'objet d'état et l'URL de l' état actuel de la page.
Rocket Hazmat
2
C'était juste étrange que je cherche des informations sur replaceState et j'ai fini par lire sur pushState: P
Giwrgos Tsopanoglou
6

Regardez l'exemple

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

et rechercher location.hash;

avalkab
la source
2

Le deuxième argument Le titre ne signifie pas le titre de la page - Il s'agit plus d'une définition / information pour l'état de cette page

Mais nous pouvons toujours changer le titre en utilisant l' événement onpopstate , et en passant le nom du titre non pas à partir du deuxième argument, mais en tant qu'attribut du premier paramètre passé en tant qu'objet

Référence: http://spoiledmilk.com/blog/html5-changing-the-browser-url-without-refreshing-page/

Mahesh
la source
2

Selon MDN History doc
Il est clairement dit que le deuxième argument est pour l'avenir utilisé pas pour le moment. Vous avez raison, le deuxième argument concerne le titre de la page Web, mais il est actuellement ignoré par tous les principaux navigateurs.

Firefox ignore actuellement ce paramètre, bien qu'il puisse l'utiliser à l'avenir. Passer la chaîne vide ici devrait être sûr contre les modifications futures de la méthode. Alternativement, vous pouvez passer un court titre pour l'état dans lequel vous vous déplacez.

Munir Khakhi
la source
Le deuxième argument ne fait pas référence au titre de la page Web - le document MDN que vous avez lié dit "transmettez un titre court à l'état vers lequel vous vous déplacez". . Cela concorde avec la documentation de l' interface d'historique du W3C qui dit "Pousse les données données dans l'historique de session, avec le titre donné" . Les données dans cette phrase sont les données d' état , donc encore une fois le titre fait référence à l'état (données).
Stephen P
1

Je voulais vraiment répondre à la réponse de @ Sev.

Sev a raison, il y a un bug à l'intérieur du window.history.replaceState

Pour résoudre ce problème, réécrivez simplement le constructeur pour définir le titre manuellement.

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);
}
L'INCROYABLE
la source
2
Ne fais pas ça. L'écrasement des fonctions par défaut est vraiment mauvais
René Roth
3
que suggérez-vous d'autre lorsque vous avez besoin de corriger ce bogue?
Glenn Plas
@GlennPlas ouvre un PR contre le repo
react
0

Supposons que https://www.mozilla.org/foo.html exécute le JavaScript suivant:

const stateObj = { foo: 'bar' };

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

Cela entraînera l'affichage de la barre d'URL https://www.mozilla.org/bar2.html , mais ne fera pas charger le navigateur de bar2.html ni même de vérifier que bar2.html existe.

cendré
la source