Как обнаружить изменение URL в JavaScript


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

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

12 ответов:

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

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

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

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

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

в противном случае да, вам придется использовать setInterval и проверить наличие изменений в хэш-событии (окно.местоположение.хэш)

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

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

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

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

С помощью jQuery

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

редактировать после небольшого исследования:

это как-то кажется, что я был обманут документацией, присутствующей на Mozilla docs. Элемент 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 Docs

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

добавить прослушиватель событий изменения хэша!

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

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

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

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

// Bad code example

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

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

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

хотя старый вопрос, на 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});

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

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

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

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

посмотрите на функцию выгрузки jQuery. Он справляется со всеми вещами.

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

выгрузка событие отправляется в элемент окна, когда пользователь переходит от страницы. Это может означать одну из многих вещей. Пользователь мог нажать на ссылку, чтобы покинуть страницу, или ввести новый URL-адрес в адресной строке. Кнопки вперед и назад вызовут событие. Закрытие окна браузера приведет к тому, что событие будет вызванный. Даже перезагрузка страницы сначала создаст событие выгрузки.

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

вы начинаете новый setInterval при каждом вызове, не отменяя предыдущий - вероятно, вы только хотели иметь setTimeout

делая небольшое расширение chrome, я столкнулся с той же проблемой с дополнительной проблемой : иногда меняется страница, но не URL.

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

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

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

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

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

таким образом, в основном решение leoneckert, примененное к истории окон, которое изменится при изменении страницы в одном приложении страницы.

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