238 votes

Comment détecter si l'URL a changé après un hachage en JavaScript ?

Comment puis-je vérifier si une URL a changé en JavaScript ? Par exemple, des sites Web comme GitHub, qui utilisent AJAX, ajouteront des informations sur la page après un symbole # pour créer une URL unique sans recharger la page. Quel est le meilleur moyen de détecter si cette URL a changé ?

  • Est-ce que le onload L'événement est rappelé ?
  • Y a-t-il un gestionnaire d'événement pour l'URL ?
  • Ou faut-il vérifier l'URL toutes les secondes pour détecter un changement ?

1 votes

Pour les futurs visiteurs, une nouvelle réponse de @aljgom de 2018 est la meilleure solution : stackoverflow.com/a/52809105/151503

2voto

Yao Bao Points 7

La réponse ci-dessous vient d'ici (avec une ancienne syntaxe javascript (pas de fonction flèche, support IE 10+)) : https://stackoverflow.com/a/52809105/9168962

(function() {
  if (typeof window.CustomEvent === "function") return false; // If not IE
  function CustomEvent(event, params) {
    params = params || {bubbles: false, cancelable: false, detail: null};
    var evt = document.createEvent("CustomEvent");
    evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
    return evt;
  }
  window.CustomEvent = CustomEvent;
})();

(function() {
  history.pushState = function (f) {
    return function pushState() {
      var ret = f.apply(this, arguments);
      window.dispatchEvent(new CustomEvent("pushState"));
      window.dispatchEvent(new CustomEvent("locationchange"));
      return ret;
    };
  }(history.pushState);
  history.replaceState = function (f) {
    return function replaceState() {
      var ret = f.apply(this, arguments);
      window.dispatchEvent(new CustomEvent("replaceState"));
      window.dispatchEvent(new CustomEvent("locationchange"));
      return ret;
    };
  }(history.replaceState);
  window.addEventListener("popstate", function() {
    window.dispatchEvent(new CustomEvent("locationchange"));
  });
})();

1voto

Alburkerk Points 675

En faisant une petite extension chrome, j'ai rencontré le même problème avec un problème supplémentaire : Parfois, la page change mais pas l'URL.

Par exemple, il suffit d'aller sur la page d'accueil de Facebook et de cliquer sur le bouton "Accueil". Vous rechargerez la page mais l'URL ne changera pas (style d'application à une page).

Dans 99% des cas, nous développons des sites web et nous pouvons donc obtenir ces événements à partir de frameworks comme Angular, React, Vue, etc.

MAIS Dans le cas de mon extension Chrome (en Vanilla JS), j'ai dû écouter un événement qui se déclenche à chaque "changement de page", qui peut généralement être détecté par le changement d'URL, mais parfois non.

Ma solution maison était la suivante :

listen(window.history.length);
var oldLength = -1;
function listen(currentLength) {
  if (currentLength != oldLength) {
    // Do your stuff here
  }

  oldLength = window.history.length;
  setTimeout(function () {
    listen(window.history.length);
  }, 1000);
}

Donc, en gros, la solution de Leoneckert, appliquée à l'historique des fenêtres, qui changera quand une page change dans une application à page unique.

Ce n'est pas très compliqué, mais c'est la solution la plus propre que j'ai trouvée, étant donné que nous ne vérifions ici que l'égalité d'un nombre entier, et non des objets plus grands ou le DOM entier.

1voto

Seph Reed Points 705

J'ai trouvé une réponse fonctionnelle dans un fil séparé :

Il n'y a pas un seul événement qui fonctionnera toujours, et le singe Parcheando l'événement pushState est assez aléatoire pour la plupart des principaux SPA.

Le sondage intelligent est donc ce qui a le mieux fonctionné pour moi. Vous pouvez ajouter autant de types d'événements que vous le souhaitez, mais ceux-ci semblent faire un très bon travail pour moi.

Écrit pour TS, mais facilement modifiable :

const locationChangeEventType = "MY_APP-location-change";

// called on creation and every url change
export function observeUrlChanges(cb: (loc: Location) => any) {
  assertLocationChangeObserver();
  window.addEventListener(locationChangeEventType, () => cb(window.location));
  cb(window.location);
}

function assertLocationChangeObserver() {
  const state = window as any as { MY_APP_locationWatchSetup: any };
  if (state.MY_APP_locationWatchSetup) { return; }
  state.MY_APP_locationWatchSetup = true;

  let lastHref = location.href;

  ["popstate", "click", "keydown", "keyup", "touchstart", "touchend"].forEach((eventType) => {
    window.addEventListener(eventType, () => {
      requestAnimationFrame(() => {
        const currentHref = location.href;
        if (currentHref !== lastHref) {
          lastHref = currentHref;
          window.dispatchEvent(new Event(locationChangeEventType));
        }
      })
    })
  });
}

Utilisation

observeUrlChanges((loc) => {
  console.log(loc.href)
})

1voto

Luis Lobo Points 33

J'ai créé ceci, il suffit d'ajouter la fonction en tant qu'argument et chaque fois que le lien a été modifié, la fonction sera exécutée et renverra l'ancienne et la nouvelle url.

J'ai créé ceci, il suffit d'ajouter la fonction en tant qu'argument et chaque fois que le lien a été modifié, la fonction sera exécutée et renverra l'ancienne et la nouvelle url.

// on-url-change.js v1 (manual verification)
let onUrlChangeCallbacks = [];
let onUrlChangeTimestamp = new Date() * 1;
function onUrlChange(callback){
    onUrlChangeCallbacks.push(callback);
};
onUrlChangeAutorun();
function onUrlChangeAutorun(){
    let oldURL = window.location.href;
    setInterval(function(){
        let newURL = window.location.href;
        if(oldURL !== newURL){
            let event = {
                oldURL: oldURL,
                newURL: newURL,
                type: 'urlchange',
                timestamp: new Date() * 1 - onUrlChangeTimestamp
            };
            oldURL = newURL;
            for(let i = 0; i < onUrlChangeCallbacks.length; i++){
                onUrlChangeCallbacks[i](event);
            };
        };
    }, 25);
};

0voto

stakantin Points 363

Regardez la fonction de déchargement de jQuery. Elle gère toutes les choses.

https://api.jquery.com/unload/

L'événement de déchargement est envoyé à l'élément window lorsque l'utilisateur quitte la page. Cela peut signifier plusieurs choses. L'utilisateur peut avoir cliqué sur un lien pour quitter la page, ou avoir tapé une nouvelle URL dans la barre d'adresse. Les boutons "avancer" et "reculer" déclenchent l'événement. La fermeture de la fenêtre du navigateur entraînera le déclenchement de l'événement. Même un rechargement de la page créera d'abord un événement de déchargement.

$(window).unload(
    function(event) {
        alert("navigating");
    }
);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X