Как обнаружить изменение URL в JavaScript
Как я могу проверить, изменился ли URL-адрес в JavaScript? Например, такие веб-сайты, как GitHub, которые используют AJAX, будут добавлять информацию о странице после символа # для создания уникального URL-адреса без перезагрузки страницы. Каков наилучший способ определить, изменяется ли этот URL-адрес?
- - это
onload
событие называется? - есть ли обработчик событий для URL-адреса?
- или URL должен проверяться каждую секунду, чтобы обнаружить изменение?
12 ответов
в современных браузерах (IE8+, FF3.6+, Chrome), вы можете просто слушать hashchange
событие on window
.
В некоторых старых браузерах, вам нужен таймер, который постоянно проверяет location.hash
. Если вы используете jQuery, есть плагин что делает именно это.
С помощью jquery (и плагина) вы можете сделать
$(window).bind('hashchange', function() {
/* things */
});
http://benalman.com/projects/jquery-hashchange-plugin/
в противном случае да, вам придется использовать setInterval и проверить изменение события хэша (window.местоположение.хэш)
обновление! Простой черновик
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. The 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();
хотя старый вопрос, на расположение-бар проект очень полезен.
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/
событие выгрузки отправляется элементу window, когда пользователь переходит от страницы. Это может означать одну из многих вещей. Пользователь мог щелкнуть ссылку, чтобы покинуть страницу, или ввести новый URL-адрес в адресной строке. Кнопки вперед и назад вызовут событие. Закрытие окна браузера вызовет событие вызванный. Даже перезагрузка страницы сначала создаст событие unload.
$(window).unload(
function(event) {
alert("navigating");
}
);
вы начинаете новый 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.