如何检测何时使用history.pushState和history.replaceState?

Bru*_*oLM 40 javascript html5 browser-history pushstate

在修改历史状态时是否可以订阅某些事件?怎么样?

Rud*_*die 24

我曾经使用它来通知何时pushStatereplaceState被称为:

// Add this:
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');

// Use it like this:
window.addEventListener('replaceState', function(e) {
    console.warn('THEY DID IT AGAIN!');
});
Run Code Online (Sandbox Code Playgroud)

但这通常是矫枉过正的.它可能不适用于所有浏览器.(我只关心我的浏览器版本.)

NB.它在Google Chrome扩展程序内容脚本中也不起作用,因为它不允许改变网站的JS环境.您可以通过插入<script>带有所述代码来解决这个问题,但这更具有过分杀伤力.


Oli*_*ale 21

应该在历史记录更改时触发onpopstate事件,您可以在代码中绑定它,如下所示:

window.onpopstate = function (event) {
  // do stuff here
}
Run Code Online (Sandbox Code Playgroud)

当页面加载时,也可以触发此事件,您可以确定是从页面加载触发事件,还是通过检查事件对象获取状态属性来使用pushState/replaceState,如果事件是由事件引起的,则将不确定页面加载

window.onpopstate = function (event) {
  if (event.state) {
    // history changed because of pushState/replaceState
  } else {
    // history changed because of a page load
  }
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,目前还没有onpushstate事件,为了解决这个问题,你需要包装pushState和replaceState方法来实现你自己的onpushstate事件.

我有一个库使得使用pushState更容易一些,它可能值得检查它叫做Davis.js,它提供了一个简单的api来处理基于pushState的路由.

  • [docs](https://developer.mozilla.org/en-US/docs/Web/Events/popstate)明确声明`pushState`不会触发`onpopstate`! (46认同)
  • Mozilla/Firefox在页面加载时不会发出onpopstate事件,但Safari/Chrome会这样做 (3认同)