Fel*_*ing 139 javascript firefox-addon browser-history pushstate
因此,现在HTML5引入history.pushState了更改浏览器历史记录,网站开始将其与Ajax结合使用,而不是更改URL的片段标识符.
可悲的是,这意味着不再能够检测到这些呼叫了onhashchange.
我的问题是:是否有可靠的方法(黑客?;))来检测网站何时使用history.pushState?规范没有说明引发的事件(至少我找不到任何东西).
我尝试创建一个外观并替换window.history为我自己的JavaScript对象,但它根本没有任何效果.
进一步说明:我正在开发一个需要检测这些更改并相应操作的Firefox附加组件.
我知道几天前有一个类似的问题,询问听一些DOM事件是否有效但我宁愿不依赖它,因为这些事件可能由于很多不同的原因而产生.
更新:
这是一个jsfiddle(使用Firefox 4或Chrome 8),显示调用onpopstate时不会触发pushState(或者我做错了什么?随意改进它!).
更新2:
另一个(侧面)问题是window.location在使用时没有更新pushState(但我已经在这里读到了这个,我认为).
gbl*_*zex 171
5.5.9.1事件定义
该popstate导航到会话历史记录条目时,事件在某些情况下被解雇.
据此,当你使用popstate时没有理由被解雇pushState.但是像pushstate这样的事件会派上用场.因为它history是一个宿主对象,你应该小心它,但在这种情况下Firefox似乎很好.这段代码工作得很好:
(function(history){
var pushState = history.pushState;
history.pushState = function(state) {
if (typeof history.onpushstate == "function") {
history.onpushstate({state: state});
}
// ... whatever else you want to do
// maybe call onhashchange e.handler
return pushState.apply(history, arguments);
};
})(window.history);
Run Code Online (Sandbox Code Playgroud)
你的jsfiddle 成为:
window.onpopstate = history.onpushstate = function(e) { ... }
Run Code Online (Sandbox Code Playgroud)
你可以window.history.replaceState用同样的方式进行猴子补丁.
注意:当然,您可以onpushstate简单地添加到全局对象,甚至可以通过它来处理更多事件add/removeListener
CBH*_*ing 11
终于找到了“正确”的方法来做到这一点!它需要为您的扩展程序添加权限并使用后台页面(不仅仅是内容脚本),但它确实有效。
您想要的事件是browser.webNavigation.onHistoryStateUpdated,当页面使用historyAPI 更改 URL时会触发该事件。它只针对您有权访问的站点触发,如果需要,您还可以使用 URL 过滤器进一步减少垃圾邮件。它需要webNavigation权限(当然还有相关域的主机权限)。
事件回调获取选项卡 ID、正在“导航”到的 URL 以及其他此类详细信息。如果您需要在事件触发时在该页面上的内容脚本中执行操作,请直接从后台页面注入相关脚本,或者让内容脚本port在加载时打开一个到后台页面,让后台页面保存由选项卡 ID 索引的集合中的该端口,并在事件触发时通过相关端口(从后台脚本到内容脚本)发送消息。
感谢@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)
},
})
})
Run Code Online (Sandbox Code Playgroud)
小智 6
除了其他答案。我们可以使用 History 接口,而不是存储原始函数。
history.pushState = function()
{
// ...
History.prototype.pushState.apply(history, arguments);
}
Run Code Online (Sandbox Code Playgroud)
我用简单的代理来做到这一点。这是原型的替代品
window.history.pushState = new Proxy(window.history.pushState, {
apply: (target: any, thisArg: any, argArray?: any) => {
// trigger here what you need
return target.apply(thisArg, argArray);
},
});
Run Code Online (Sandbox Code Playgroud)
我曾经使用过这个:
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!');
});
Run Code Online (Sandbox Code Playgroud)
这几乎和galambalazs做的一样。
不过这通常是矫枉过正。它可能不适用于所有浏览器。(我只关心我的浏览器版本。)
(它留下了一个 var _wr,所以你可能想要包装它或其他东西。我不在乎那个。)
| 归档时间: |
|
| 查看次数: |
66555 次 |
| 最近记录: |