Подтвердить что ты не робот

Как определить изменение URL-адреса в JavaScript

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

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

Ответ 1

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

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

Ответ 2

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

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

с jQuery

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

Ответ 3

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

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

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

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

Update! Простой черновик

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

Ответ 4

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

Почему-то кажется, что меня одурачила документация, представленная в документации по Mozilla. Событие popstate (и его функция обратного вызова onpopstate) не запускаются всякий раз, когда в pushState() вызываются 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% браузеров по всему миру.

Ответ 5

То, что я хотел, было иметь возможность добавить 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'))
});

Ответ 6

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

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  
}

Ответ 7

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

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

Ответ 8

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

Ответ 9

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

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

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

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

Ответ 10

Посмотрите на функцию разгрузки jQuery. Он обрабатывает все.

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

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

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

Ответ 11

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

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

В 99% случаев мы разрабатываем веб-сайты, чтобы мы могли получать такие события от Frameworks, как 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;
  setTimeout(function () {
    listen(window.history.length);
  }, 1000);
}

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

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

Ответ 12

window.addEventListener("beforeunload", function (e) {
    // do something
}, false);

Ответ 13

Вы запускаете новый setInterval при каждом вызове без отмены предыдущего - возможно, вы имели в виду только setTimeout

Ответ 14

Ответ ниже приходит отсюда (со старым синтаксисом javascript (без функции стрелки, поддержка IE 10+)): fooobar.com/info/69572/...

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