现在HTML5引入了历史。pushState来改变浏览器的历史记录,网站开始与Ajax结合使用,而不是改变URL的片段标识符。
不幸的是,这意味着onhashchange再也不能检测到这些调用了。
我的问题是:有没有可靠的方法(hack?);))来检测网站何时使用history.pushState?规范没有说明引发的任何事件(至少我没有找到任何事件)。
我试图创造一个立面,并替换了窗户。我自己的JavaScript对象的历史,但它根本没有任何影响。
进一步解释:我正在开发一个Firefox插件,它需要检测这些变化并采取相应的行动。
我知道几天前有一个类似的问题,问监听一些DOM事件是否有效,但我宁愿不依赖于它,因为这些事件可以出于许多不同的原因生成。
更新:
这里是一个jsfiddle(使用Firefox 4或Chrome 8),显示onpopstate没有触发pushState被调用(或我做错了什么?请随意改进!)。
更新2:
另一个问题是那个窗口。使用pushState时,location不会更新(但我已经在这里读到这个,所以我认为)。
因为我只是想要新的URL,我已经适应了@gblazex和@Alberto S.的代码来得到这个:
(function(history){
var pushState = history.pushState;
history.pushState = function(state, key, path) {
if (typeof history.onpushstate == "function") {
history.onpushstate({state: state, path: path})
}
pushState.apply(history, arguments)
}
window.onpopstate = history.onpushstate = function(e) {
console.log(e.path)
}
})(window.history);
我曾经用过这个:
var _wr = function(type) {
var orig = history[type];
return function() {
var rv = orig.apply(this, arguments);
var e = new Event(type);
e.arguments = arguments;
window.dispatchEvent(e);
return rv;
};
};
history.pushState = _wr('pushState'), history.replaceState = _wr('replaceState');
window.addEventListener('replaceState', function(e) {
console.warn('THEY DID IT AGAIN!');
});
几乎和galambalazs一样。
但这通常是过度的。而且它可能并不适用于所有浏览器。(我只关心我的浏览器版本。)
(它会留下一个var _wr,所以你可能想要把它换行。我不关心这个。)
谢谢@KalanjDjordjeDjordje的回答。我试图让他的想法成为一个完整的解决方案:
const onChangeState = (state, title, url, isReplace) => {
// define your listener here ...
}
// set onChangeState() listener:
['pushState', 'replaceState'].forEach((changeState) => {
// store original values under underscored keys (`window.history._pushState()` and `window.history._replaceState()`):
window.history['_' + changeState] = window.history[changeState]
window.history[changeState] = new Proxy(window.history[changeState], {
apply (target, thisArg, argList) {
const [state, title, url] = argList
onChangeState(state, title, url, changeState === 'replaceState')
return target.apply(thisArg, argList)
},
})
})