web-dev-qa-db-fra.com

Comment détecter quand history.pushState et history.replaceState sont utilisés?

Y a-t-il un événement auquel je peux m'abonner lorsque l'état de l'historique est modifié? Comment?

39
BrunoLM

L'événement onpopstate doit être déclenché lorsque l'historique change, vous pouvez le lier dans votre code comme ceci:

window.onpopstate = function (event) {
  // do stuff here
}

Cet événement peut également être déclenché lors du chargement de la page, vous pouvez déterminer si l'événement a été déclenché à partir d'un chargement de page, ou en utilisant pushState/replaceState en vérifiant l'objet événement pour une propriété d'état, il ne sera pas défini si l'événement a été provoqué par un chargement de page

window.onpopstate = function (event) {
  if (event.state) {
    // history changed because of pushState/replaceState
  } else {
    // history changed because of a page load
  }
}

Il n'y a actuellement aucun événement onpushstate malheureusement, pour contourner ce problème, vous devez encapsuler les méthodes pushState et replaceState pour implémenter votre propre événement onpushstate.

J'ai une bibliothèque qui facilite le travail avec pushState, il vaut peut-être la peine de la consulter appelée Davis.js , elle fournit une API simple pour travailler avec le routage basé sur pushState.

25
Oliver Nightingale

J'avais l'habitude de l'utiliser pour être également averti lorsque pushState et replaceState étaient appelés:

// Add this:
var _wr = function(type) {
    var orig = history[type];
    return function() {
        var rv = orig.apply(this, arguments);
        var e = new Event(type);
        e.arguments = arguments;
        window.dispatchEvent(e);
        return rv;
    };
};
history.pushState = _wr('pushState'), history.replaceState = _wr('replaceState');

// Use it like this:
window.addEventListener('replaceState', function(e) {
    console.warn('THEY DID IT AGAIN!');
});

C'est généralement exagéré cependant. Et cela pourrait ne pas fonctionner dans tous les navigateurs. (Je me soucie seulement de ma version de mon navigateur.)

NB. Il ne fonctionne pas non plus dans Google Chrome scripts de contenu d'extension, car il n'est pas autorisé de modifier l'environnement JS du site. Vous pouvez contourner cela en insérant un <script> avec ce code, mais c'est encore plus exagéré.

22
Rudie