如何检查URL是否在JavaScript中发生了变化?例如,像GitHub这样使用AJAX的网站,会在#符号后附加页面信息,以创建唯一的URL,而无需重新加载页面。检测该URL是否发生变化的最佳方法是什么?
是否再次调用onload事件? 是否有URL的事件处理程序? 或者必须每秒钟检查URL以检测更改?
如何检查URL是否在JavaScript中发生了变化?例如,像GitHub这样使用AJAX的网站,会在#符号后附加页面信息,以创建唯一的URL,而无需重新加载页面。检测该URL是否发生变化的最佳方法是什么?
是否再次调用onload事件? 是否有URL的事件处理程序? 或者必须每秒钟检查URL以检测更改?
当前回答
享受吧!
var previousUrl = '';
var observer = new MutationObserver(function(mutations) {
if (location.href !== previousUrl) {
previousUrl = location.href;
console.log(`URL changed to ${location.href}`);
}
});
其他回答
用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();
如果没有窗口事件为您工作(在我的例子中不是这样),您还可以使用MutationObserver来查看根元素(非递归地)。
// capture the location at page load
let currentLocation = document.location.href;
const observer = new MutationObserver((mutationList) => {
if (currentLocation !== document.location.href) {
// location changed!
currentLocation = document.location.href;
// (do your event logic here)
}
});
observer.observe(
document.getElementById('root'),
{
childList: true,
// important for performance
subtree: false
});
这可能并不总是可行的,但通常情况下,如果URL更改,根元素的内容也会更改。
我没有进行概要分析,但从理论上讲,这比计时器的开销要小,因为Observer模式通常是实现的,因此当发生更改时,它只是通过订阅进行循环。我们在这里只添加了一个订阅。另一方面,计时器必须非常频繁地检查,以确保在URL更改后立即触发事件。
此外,这比计时器更可靠,因为它消除了计时问题。
享受吧!
var previousUrl = '';
var observer = new MutationObserver(function(mutations) {
if (location.href !== previousUrl) {
previousUrl = location.href;
console.log(`URL changed to ${location.href}`);
}
});
在一个单独的线程中找到了一个工作答案:
没有一个事件是永远有效的,对于大多数大型spa来说,monkey patch pushState事件是非常偶然的。
所以聪明的投票对我来说是最有效的。您可以添加任意多的事件类型,但这些似乎对我来说做得很好。
为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)
})
在做一点chrome扩展时,我遇到了一个额外的问题:有时,页面变化而不是URL。
例如,只要进入Facebook主页,然后点击“主页”按钮。你将重新加载页面,但URL不会改变(单页应用程序样式)。
99%的时间里,我们在开发网站,这样我们就可以从Angular、React、Vue等框架中获取这些事件。
但是,在我的Chrome扩展(在香草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。