Как обнаружить изменение URL в JavaScript - PullRequest
110 голосов
/ 17 июня 2011

Как я могу проверить, изменился ли URL в JavaScript? Например, веб-сайты, такие как GitHub, которые используют AJAX, будут добавлять информацию о странице после символа #, чтобы создать уникальный URL-адрес без перезагрузки страницы. Как лучше всего определить, изменяется ли этот URL-адрес?

  • Повторно ли вызывается событие onload?
  • Есть ли обработчик событий для URL?
  • Или URL должен проверяться каждую секунду, чтобы обнаружить изменение?

Ответы [ 13 ]

89 голосов
/ 17 июня 2011

В современных браузерах (IE8 +, FF3.6 +, Chrome) вы можете просто прослушивать событие hashchange на window.

В некоторых старых браузерах вам нужен таймер, который постоянно проверяет location.hash. Если вы используете jQuery, есть плагин , который делает именно это.

65 голосов
/ 07 мая 2016

используйте этот код

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

с jQuery

$(window).bind('hashchange', function() {
     //code
});
54 голосов
/ 17 июня 2011

С помощью jquery (и плагина) вы можете сделать

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

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

В противном случае да, вам придется использовать setInterval и проверить изменения в хэшесобытие (window.location.hash)

Обновление!Простой проект

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();
39 голосов
/ 24 января 2017

РЕДАКТИРОВАТЬ после небольшого исследования:

Почему-то кажется, что меня обманула документация, представленная в документах Mozilla. Событие popstate (и его функция обратного вызова onpopstate) не запускаются всякий раз, когда в коде вызываются pushState() или replaceState(). Поэтому первоначальный ответ применим не во всех случаях.

Однако есть способ обойти это, исправляя функции в соответствии с @ alpha123 :

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

Оригинальный ответ

Учитывая, что заголовок этого вопроса " Как обнаружить изменение URL ", ответ, когда вы хотите знать, когда меняется полный путь (а не только хэш-привязка), заключается в том, что вы можете прослушайте событие popstate:

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

Ссылка для popstate в Документах Mozilla

В настоящее время (январь 2017 г.) существует поддержка popstate от 92% браузеров по всему миру.

22 голосов
/ 15 октября 2018

Я хотел добавить locationchange прослушивателей событий, и с этой модификацией мы можем делать такие вещи

window.addEventListener('locationchange', function(){
    console.log('location changed!');
})

Напротив, window.addEventListener('hashchange',()=>{}) сработает, только если часть после хэштега в URL-адресе изменится, а window.addEventListener('popstate',()=>{}) не всегда работает.

Эта модификация, аналогичная ответу Кристиана , изменяет объект истории для добавления некоторой функциональности.

По умолчанию есть событие popstate, но для pushstate и replacestate.

нет событий.

Это модифицирует эти три функции, так что все они запускают пользовательское событие locationchange, которое вы можете использовать, а также события pushstate и replacestate, если вы хотите их использовать:

/* These are the modifications: */
history.pushState = ( f => function pushState(){
    var ret = f.apply(this, arguments);
    window.dispatchEvent(new Event('pushState'));
    window.dispatchEvent(new Event('locationchange'));
    return ret;
})(history.pushState);

history.replaceState = ( f => function replaceState(){
    var ret = f.apply(this, arguments);
    window.dispatchEvent(new Event('replaceState'));
    window.dispatchEvent(new Event('locationchange'));
    return ret;
})(history.replaceState);

window.addEventListener('popstate',()=>{
    window.dispatchEvent(new Event('locationchange'))
});
18 голосов
/ 02 июня 2017

Добавить слушатель события изменения хеша!

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

Или, чтобы прослушать все изменения URL:

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

Это лучше, чем приведенный ниже код, потому что в window.onhashchange может существовать только одна вещь, и вы, возможно, будете перезаписывать чужой код.

// Bad code example

window.onhashchange = function() { 
     // Code that overwrites whatever was previously in window.onhashchange  
}
6 голосов
/ 06 апреля 2016

у меня это решение сработало:

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();
5 голосов
/ 20 мая 2015

Хотя старый вопрос, проект Location-bar очень полезен.

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
// e.g. 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});
3 голосов
/ 20 декабря 2017

Чтобы прослушать изменения URL, см. Ниже:

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

Используйте этот стиль, если вы собираетесь остановить / удалить слушателя после некоторого определенного условия.

window.addEventListener('popstate', function(e) {
   console.log('url changed')
});
1 голос
/ 11 апреля 2018

При создании небольшого расширения для Chrome я столкнулся с той же проблемой, связанной с дополнительной проблемой: Иногда страница меняется, но не URL-адрес.

Например, просто перейдите на FacebookДомашняя страница и нажмите кнопку «Домой».Вы перезагрузите страницу, но URL-адрес не изменится (стиль одностраничного приложения).

99% времени, мы занимаемся разработкой веб-сайтов, чтобы мы могли получать эти события из таких фреймворков, как Angular, React, Vueи т. д.

НО , в моем случае расширение Chrome (в Vanilla JS) мне пришлось прослушивать событие, которое будет запускаться для каждого «изменения страницы», которое обычно можетбыть измененным, но иногда это не так.

Мое домашнее решение было следующим:

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

Таким образом, в основном решение leoneckert, примененное к истории окон, будет меняться, когдастраница меняется в одностраничном приложении.

Не ракетостроение, а самое чистое решение, которое я нашел, учитывая, что мы здесь проверяем только целочисленное равенство, а не более крупные объекты или весь DOM.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...