如何在JavaScript中检查URL是否已更改?例如,像GitHub这样使用AJAX的网站会在#符号后附加页面信息以创建唯一的URL而无需重新加载页面。检测URL更改的最佳方法是什么?
- 是否再次调用
onload
事件? - 是否有URL的事件处理程序?
- 还是必须每秒检查一次URL以检测更改?
如何在JavaScript中检查URL是否已更改?例如,像GitHub这样使用AJAX的网站会在#符号后附加页面信息以创建唯一的URL而无需重新加载页面。检测URL更改的最佳方法是什么?
onload
事件?要监听URL的变化,请参见以下内容:
window.onpopstate = function(event) {
console.log("location: " + document.location + ", state: " + JSON.stringify(event.state));
};
如果您打算在某些特定条件后停止/删除监听器,请使用此样式。
window.addEventListener('popstate', function(e) {
console.log('url changed')
});
虽然这是一个老问题,但Location-bar项目非常有用,特别是在IT技术方面。
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});
(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"));
});
})();
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);
}
window.history
的最大长度为50(至少在Chrome 80中是这样)。在此之后,window.history.length
始终返回50。当发生这种情况时,该方法将无法识别任何更改。 - Collin Krawll// onurlchange-event.js v1.0.1
(() => {
const hasNativeEvent = Object.keys(window).includes('onurlchange')
if (!hasNativeEvent) {
let oldURL = location.href
setInterval(() => {
const newURL = location.href
if (oldURL === newURL) {
return
}
const urlChangeEvent = new CustomEvent('urlchange', {
detail: {
oldURL,
newURL
}
})
oldURL = newURL
dispatchEvent(urlChangeEvent)
}, 25)
addEventListener('urlchange', event => {
if (typeof(onurlchange) === 'function') {
onurlchange(event)
}
})
}
})()
使用示例:
window.onurlchange = event => {
console.log(event)
console.log(event.detail.oldURL)
console.log(event.detail.newURL)
}
addEventListener('urlchange', event => {
console.log(event)
console.log(event.detail.oldURL)
console.log(event.detail.newURL)
})
addEventListener
和 dispatchEvent
所做的事情。你可以使用 addEventListener(eventType, function)
来保存回调函数,当你分发一个事件时,所有的函数都会被调用。 - aljgom在另一个线程中找到了一个可行的答案:
没有一个事件总是有效的,而对于大多数主要的单页应用程序,猴子补丁推送状态事件往往效果不佳。
因此,智能轮询对我来说效果最好。您可以添加任意数量的事件类型,但这些似乎对我来说非常有效。
针对TS编写,但易于修改:
const locationChangeEventType = "MY_APP-location-change";
// called on creation and every url change
export function observeUrlChanges(cb: (loc: Location) => any) {
assertLocationChangeObserver();
window.addEventListener(locationChangeEventType, () => cb(window.location));
cb(window.location);
}
function assertLocationChangeObserver() {
const state = window as any as { MY_APP_locationWatchSetup: any };
if (state.MY_APP_locationWatchSetup) { return; }
state.MY_APP_locationWatchSetup = true;
let lastHref = location.href;
["popstate", "click", "keydown", "keyup", "touchstart", "touchend"].forEach((eventType) => {
window.addEventListener(eventType, () => {
requestAnimationFrame(() => {
const currentHref = location.href;
if (currentHref !== lastHref) {
lastHref = currentHref;
window.dispatchEvent(new Event(locationChangeEventType));
}
})
})
});
}
observeUrlChanges((loc) => {
console.log(loc.href)
})
https://api.jquery.com/unload/
当用户从页面导航离开时,卸载事件将发送到窗口元素。这可能意味着许多事情。用户可能单击链接以离开页面,或在地址栏中键入新的URL。前进和后退按钮将触发该事件。关闭浏览器窗口将导致触发该事件。即使页面重新加载,也会首先创建一个卸载事件。$(window).unload(
function(event) {
alert("navigating");
}
);
window.addEventListener("beforeunload", function (e) {
// do something
}, false);
您每次调用时都会启动一个新的setInterval
,而不取消先前的一个 - 可能您只想要一个setTimeout
享受!
var previousUrl = '';
var observer = new MutationObserver(function(mutations) {
if (location.href !== previousUrl) {
previousUrl = location.href;
console.log(`URL changed to ${location.href}`);
}
});