Come rilevare la modifica dell’URL in JavaScript

Come posso verificare se un URL è cambiato in JavaScript? Ad esempio, siti web come GitHub, che utilizzano AJAX, aggiungeranno informazioni sulla pagina dopo un simbolo # per creare un URL univoco senza ricaricare la pagina. Qual è il modo migliore per rilevare se questo URL cambia?

  • L’evento onload è di nuovo chiamato?
  • Esiste un gestore di eventi per l’URL?
  • O l’URL deve essere controllato ogni secondo per rilevare una modifica?

Nei browser moderni (IE8 +, FF3.6 +, Chrome), puoi semplicemente ascoltare l’evento hashchange sulla window .

In alcuni vecchi browser, hai bisogno di un timer che controlli continuamente location.hash . Se stai usando jQuery, c’è un plugin che fa esattamente questo.

Con jquery (e un plug-in) puoi fare

 $(window).bind('hashchange', function() { /* things */ }); 

http://benalman.com/projects/jquery-hashchange-plugin/

Altrimenti sì, dovresti usare setInterval e verificare una modifica nell’evento hash (window.location.hash)

Aggiornare! Una semplice bozza

 function hashHandler(){ this.oldHash = window.location.hash; this.Check; var that = this; var detect = function(){ if(that.oldHash!=window.location.hash){ alert("HASH CHANGED - new has" + window.location.hash); that.oldHash = window.location.hash; } }; this.Check = setInterval(function(){ detect() }, 100); } var hashDetection = new hashHandler(); 

usa questo codice

 window.onhashchange = function() { //code } 

con jQuery

 $(window).bind('hashchange', function() { //code }); 

EDIT dopo un po ‘di ricerca:

Sembra in qualche modo che io sia stato ingannato dalla documentazione presente su Mozilla docs. L’evento popstate (e la sua funzione di callback onpopstate ) non vengono triggersti ogni volta che vengono chiamati in codice pushState() o replaceState() . Pertanto la risposta originale non si applica in tutti i casi.

Tuttavia, esiste un modo per aggirare questo problema applicando le patch alle scimmie secondo @ alpha123 :

 var pushState = history.pushState; history.pushState = function () { pushState.apply(history, arguments); fireEvents('pushState', arguments); // Some event-handling function }; 

Risposta originale

Dato che il titolo di questa domanda è ” Come rilevare la modifica dell’URL “, quando vuoi sapere quando il percorso completo cambia (e non solo l’ancora hash), puoi ascoltare l’evento popstate :

 window.onpopstate = function(event) { console.log("location: " + document.location + ", state: " + JSON.stringify(event.state)); }; 

Riferimento per popstate in Mozilla Docs

Attualmente (gennaio 2017) c’è supporto per popstate dal 92% dei browser in tutto il mondo.

Aggiungi un listener di eventi di modifica hash!

 window.addEventListener('hashchange', function(e){console.log('hash changed')}); 

Oppure, per ascoltare tutte le modifiche dell’URL:

 window.addEventListener('popstate', function(e){console.log('url changed')}); 

Questo è meglio di qualcosa come il seguente codice perché solo una cosa può esistere in window.onhashchange e probabilmente sovrascriveresti il ​​codice di qualcun altro.

 // Bad code example window.onhashchange = function() { // Code that overwrites whatever was previously in window.onhashchange } 

questa soluzione ha funzionato per me:

 var oldURL = ""; var currentURL = window.location.href; function checkURLchange(currentURL){ if(currentURL != oldURL){ alert("url changed!"); oldURL = currentURL; } oldURL = window.location.href; setInterval(function() { checkURLchange(window.location.href); }, 1000); } checkURLchange(); 

Sebbene sia una vecchia domanda, il progetto Barra di posizione è molto utile.

 var LocationBar = require("location-bar"); var locationBar = new LocationBar(); // listen to all changes to the location bar locationBar.onChange(function (path) { console.log("the current url is", path); }); // listen to a specific change to location bar // eg Backbone builds on top of this method to implement // it's simple parametrized Backbone.Router locationBar.route(/some\-regex/, function () { // only called when the current url matches the regex }); locationBar.start({ pushState: true }); // update the address bar and add a new entry in browsers history locationBar.update("/some/url?param=123"); // update the address bar but don't add the entry in history locationBar.update("/some/url", {replace: true}); // update the address bar and call the `change` callback locationBar.update("/some/url", {trigger: true}); 

Per ascoltare le modifiche dell’URL, vedi sotto:

 window.onpopstate = function(event) { console.log("location: " + document.location + ", state: " + JSON.stringify(event.state)); }; 

Usa questo stile se hai intenzione di fermare / rimuovere il listener dopo una certa condizione.

 window.addEventListener('popstate', function(e) { console.log('url changed') }); 

Guarda la funzione jQuery di scarico. Gestisce tutte le cose.

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

L’evento di scarico viene inviato all’elemento della finestra quando l’utente si allontana dalla pagina. Questo potrebbe significare una delle tante cose. L’utente avrebbe potuto fare clic su un collegamento per uscire dalla pagina o digitare un nuovo URL nella barra degli indirizzi. I pulsanti avanti e indietro attiveranno l’evento. La chiusura della finestra del browser causerà l’triggerszione dell’evento. Anche un ricaricamento di una pagina creerà prima un evento di scarico.

 $(window).unload( function(event) { alert("navigating"); } ); 
 window.addEventListener("beforeunload", function (e) { // do something }, false); 

Stai iniziando un nuovo setInterval ad ogni chiamata, senza cancellare quello precedente – probabilmente hai solo intenzione di avere un setTimeout

Facendo una piccola estensione di chrome, ho affrontato lo stesso problema con un ulteriore problema: a volte la pagina cambia ma non l’URL.

Ad esempio, basta andare su Facebook Home page e fare clic sul pulsante “Home”. Ricarrai la pagina ma l’URL non cambierà (stile app di una sola pagina).

Il 99% delle volte stiamo sviluppando siti Web in modo da poter ottenere quegli eventi da Framework come Angular, React, Vue ecc.

MA , nel mio caso di un’estensione di Chrome (in Vanilla JS), ho dovuto ascoltare un evento che si innescherà per ogni “cambio di pagina”, che in genere può essere rilevato dall’URL modificato, ma a volte no.

La mia soluzione casalinga era la seguente:

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

Quindi, fondamentalmente la soluzione leoneckert, applicata alla cronologia delle windows, che cambierà quando una pagina cambia in una singola app.

Non la scienza missilistica, ma la soluzione più pulita che ho trovato, considerando che stiamo controllando solo l’uguaglianza di interi qui, e non gli oggetti più grandi o l’intero DOM.