如何检查URL是否在JavaScript中发生了变化?例如,像GitHub这样使用AJAX的网站,会在#符号后附加页面信息,以创建唯一的URL,而无需重新加载页面。检测该URL是否发生变化的最佳方法是什么?
是否再次调用onload事件? 是否有URL的事件处理程序? 或者必须每秒钟检查URL以检测更改?
如何检查URL是否在JavaScript中发生了变化?例如,像GitHub这样使用AJAX的网站,会在#符号后附加页面信息,以创建唯一的URL,而无需重新加载页面。检测该URL是否发生变化的最佳方法是什么?
是否再次调用onload事件? 是否有URL的事件处理程序? 或者必须每秒钟检查URL以检测更改?
当前回答
当点击链接将你重定向到同一域名的不同页面时,这些似乎都不起作用。因此,我提出了自己的解决方案:
let pathname = location.pathname;
window.addEventListener("click", function() {
if (location.pathname != pathname) {
pathname = location.pathname;
// code
}
});
编辑:您还可以检查popstate事件(如果用户返回一个页面)
window.addEventListener("popstate", function() {
// code
});
最好的祝愿,
微积分
其他回答
我希望能够添加locationchange事件监听器。经过下面的修改,我们就可以这样做了
window.addEventListener('locationchange', function () {
console.log('location changed!');
});
相比之下,window.addEventListener('hashchange',() =>{})只会在url中标签后的部分发生变化时触发,而window.addEventListener('popstate',() =>{})并不总是工作。
这种修改类似于Christian的回答,修改了history对象以添加一些功能。
默认情况下,在这些修改之前,有一个popstate事件,但是没有pushstate和replacestate事件。
这将修改这三个函数,以便所有函数都触发一个自定义locationchange事件供您使用,如果您想使用这些事件,还可以推送state和replacestate事件。
这些是修改:
(() => {
let oldPushState = history.pushState;
history.pushState = function pushState() {
let ret = oldPushState.apply(this, arguments);
window.dispatchEvent(new Event('pushstate'));
window.dispatchEvent(new Event('locationchange'));
return ret;
};
let oldReplaceState = history.replaceState;
history.replaceState = function replaceState() {
let ret = oldReplaceState.apply(this, arguments);
window.dispatchEvent(new Event('replacestate'));
window.dispatchEvent(new Event('locationchange'));
return ret;
};
window.addEventListener('popstate', () => {
window.dispatchEvent(new Event('locationchange'));
});
})();
注意,我们正在创建一个闭包,将旧函数保存为新函数的一部分,以便在调用新函数时调用它。
用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();
经过一番研究后编辑:
不知怎么的,我似乎被Mozilla文档上的文档愚弄了。当代码中调用pushState()或replaceState()时,popstate事件(及其回调函数onpopstate)不会被触发。因此,原来的答案并不适用于所有情况。
然而,有一种方法可以绕过这个问题,根据@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));
};
在Mozilla Docs中引用popstate
目前(2017年1月)全球92%的浏览器支持popstate。
下面的答案来自这里(使用旧的javascript语法(没有箭头函数,支持IE 10+)): https://stackoverflow.com/a/52809105/9168962
(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"));
});
})();
在做一点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。