Open luokuning opened 8 years ago
赞一个,学到了
感谢你的答案非常好,但是我还想区分点击是后退还是前进,这个怎么去判断呢?
@songdengwei 之前没有考虑到前进按钮,其实前进按钮也会触发 popstate
事件。如果是使用了 HTML5 的 history api 的单页应用,可以在 pushState
的时候给要入栈的状态对象加上一个字段来区分历史栈中每个状态的先后顺序,比如 pushState({s: 'a.html', index: 0}, '', 'a.html')
和 pushState({s: 'b.html', index: 1}, '', 'b.html')
,这样当点击浏览器前进后退按钮的时候我们可以通过比较 e.state.index
和当前 history.state.index
的值来判断具体是入栈还是出栈,不过这只是一个初始的想法,并没有实践过。 如果是多页面应用的话还没有想到什么方法来区分前进后退按钮。
浏览器的回退按钮可以用popstate事件监听,为什么我点击浏览器的后退按钮监听不到呢?
@TheSaltwaterRoom 请问你是直接在控制台输入的类似 window.onpopstate
这样的监听代码吗?popstate
事件被触发是在激活状态的历史条目发生改变的时候,也就是说在监听之前应该先用 history.pushState
方法往历史栈中推一条数据,这个时候点击回退按钮才会触发 popstate
事件。
我现在在代码里直接写的是if (history.pushState) {} 这样可以监听到,大神可以加一下QQ好友吗?
@TheSaltwaterRoom 不怎么用 qq... 这里有代码高亮很方便,你可以直接在这里贴出比较完整一点的代码哦
我用这种方法监听浏览器后退按钮就监测不到,然后只能用 if(history.pushState),才可以.一开始我用H5的localStorage来缓存我需要的数据,然后在用户点击手机上的返回键的时候,再把缓存的信息读取出来 window.addEventListener('popstate', function(e) { }, false);
在window.addEventListner前面调用一下history.pushState就可刷新。 var detectBack = {
initialize: function() {
console.log('stat2e', window.addEventListener)
//监听hashchange事件
window.addEventListener('hashchange', function() {
console.log(111)
//为当前导航页附加一个tag
this.history.replaceState('hasHash', '', '');
}, false);
history.pushState(1, '', '')
window.onpopstate = function(e) {
console.log(e, e.state)
if (!e.state) {
//侦测是用户触发的后退操作, dosomething
//这里刷新当前url
window.location.reload();
}
};
}
}
太感谢了,帮我解决了这个棘手的问题!
赞!
感谢楼主,但是有个疑问,这个监听用户后退事件是不是只能监听地址发生改变,但是页面不刷新的情况?
果然还是要上google才容易找得到答案。
学习了。 👍
有个场景是 支付时打开第三方支付页面,支付成功返回自己的页面,根据返回的状态判断replaceState跳转支付成功页,这时在成功页点击返回会跳到第三方,然后第三方根据订单号判断已经支付又重定向到成功页,造成循环。目前在成功页监听返回已经ok了,在成功页点击返回 监听到了就go(-3),跳转到商品详情页,但是这时候还是可以点击前进的,安卓上不好处理
不好意思 已经解决了 在返回到商品详情页时,再次pushState一个#就把之前的清空了 thx
我是在本地建了两个html页面,从页面A跳到页面B,然后在B页面的时候点击浏览器的回退,还是跳到了A页面,感觉就是没生效。。我就直接把这个代码复制在页面B上了
@zhaomenglu 如果是在你这种情况下测试的话,上面的代码需要在 initialize
方法里加一条 history.pushState(1, '', '')
,主动推一条记录到历史栈中。不过有一点需要注意,对于新版的 Chrome 浏览器,跳转到 B 页面之后,用户需要在 B 页面里做一些操作(比如点击元素、输入等等),才能在点击回退按钮的时候触发 popstate
事件。
google 版本85 也需要进行一些操作才可以出发
在 vue 中,页面挂载的时候添加监听,还是监听不到回退,求解
突发奇想,能不能监听点击浏览器的后退按钮事件。
监听。window.onbeforeunload
即可pushState/replaceState
来实现的导航,那么当浏览器回退的时候会触发window
上的popstate
事件。这时需要监听window.onpopstate
事件;hashChange
实现的导航,那么这个时候就比较麻烦。因为页面根据hash
正常变化跳转(导航)的时候也会触发popstate
事件,所以不能简单的监听popstate
事件来做出判断。开始的时候对于这种情况我也没有解决思路,于是带上梯子墙内外找了一通。果不其然,stackoverflow 上一个问题里的一个答案 (点来点去不小心把链接丢了:cry:) 给了一个思路:因为后退按钮属于浏览器的UI,并不属于任何一个页面,所以如果当鼠标在当前页面外时,监听的
popstate
事件被触发,那么认为用户点击了浏览器的后退按钮 (这里的判断鼠标是否在当前页面里是通过监听document.onmouseleave
和document.onmouseenter
事件);另外答案里还绑定了对Backspace
键的监听,因为某些浏览器默认当页面焦点不属于输入域时触发的是后退操作。这个方法基本可以满足大多数情况,但是如果用户是通过鼠标侧键 (常见于游戏鼠标) 来实现的后退操作,那么可能就无法监听了。我一直相信黄天不负有心人这句话在大多数情况下都是可以被验证的,而且也相信自己的运气不会太差,因为我爱笑。好了回到正题,说实话对于怎么解决这个问题我想了整整一下午,最后不知不觉敲下了这么一段代码:
这样就不用监听鼠标或键盘事件了:grin:。代码很简单,也有详细的注释,这里就不在花篇幅解释了,有疑问的话就请留言吧。
其实前进后退按钮都会触发
popstate
事件,MDN 里解释说每当激活的历史记录发生变化时,都会触发popstate
事件。在新版的 Chrome 中 (我测试的版本是 79,具体从哪一版本开始的变更暂不清楚),如果你的页面不是单页应用,而且采用的是在
initialize
方法中手动执行history.pushState(1, '', '')
推入一条历史记录从而监听历史栈的变动,那么如果用户没在目标页面做任何操作(点击、输入等等),直接点击回退按钮的话,是无法触发popstate
事件的,也就是说这个方法会失效。