我正在尝试区分两种类型的URL更改。
基本使用pushstate
,可以从http://example.com
移至http://example.com/account
,而无需重新加载页面(此处为an example)。
可以通过以下技巧来检测这些变化(摘自[here](How to detect URL change in JavaScript)):
/* Add a locationstorage event in the window */
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'))
});
// Capture the locationchange event
window.addEventListener('locationchange', function(){
console.log('location changed!');
});
尽管,我意识到它还可以捕获Hash URL的更改,例如http://example.com#about
。我知道可以通过以下方式捕获哈希URL的更改:
$(window).bind('hashchange', function() {
/* things */
});
我的问题是散列更改还会触发popstate
(在历史记录中)(see here)。
我将如何区分这两种类型的事件?
[我担心必须依靠正则表达式来获取哈希,但是我刚刚意识到Location
对象已经从URL中解析了哈希。
我要做的就是在事件发生之前和之后从该位置捕获哈希值(并保持更新);
因此,在当前位置引入一个变量:
current_hash = window.location.hash;
并使用它来区分URL更改的类型(保持更新):
window.addEventListener('popstate', (ev) => {
if (ev.target.location.hash == current_hash){
window.dispatchEvent(new Event('locationchange'));
} else {
current_hash = ev.target.location.hash;
}
});
# variable that keeps the current hash
current_hash = window.location.hash;
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', (ev) => {
# use it to distinguish the event
if (ev.target.location.hash == current_hash){
window.dispatchEvent(new Event('locationchange'));
} else {
# keep current hash updated
current_hash = ev.target.location.hash;
}
});
window.addEventListener('locationchange', function(event){
console.log('location changed!');
})