问题描述
foo页面有个返回挽留的弹窗,点击自定义的返回箭头是ok的,但是如果使用android的物理返回键就GG了。
解决思路
window.addEventListener('popstate', cb)来接管浏览器的返回按钮操作,也就是adnroid上面的物理返回操作。
遇到的问题
- 直接在foo页面注册了popstate后,发现点击浏览器的返回按钮并没有执行popstate的cb
- 解决方案就是注册popstate之后,直接history.pushState,这样在点击浏览器的返回按钮的时候才能出发popstate事件。
案例分析
- foo页面注册popstate,执行alert(2), 然后pushState到bar页面,此时访问baidu.com。点击返回回到bar页面,不会触发alert(2),在bar页面继续点击返回回到foo页面,依然不会触发alert(2),在foo页面继续点击返回按钮,回到上个页面,还是没有alert(2)。
- 为何baidu回到bar没有alert(2)?
- 因为baidu并没有注册popstate
- 为何bar回到foo没有alert(2)?
- 因为bar页面也没有注册popstate
- 为何foo返回没有alert(2)?
- 因为foo页面没有执行pushState
- 为何baidu回到bar没有alert(2)?
总结
通过遇到的问题以及案例分析,我们得知要想在foo页面触发popstate需要满足两个条件,1:foo页面注册了popstate 2:foo页面执行了pushState
// physicalBack.js
const physicalBack = {
register(cb) {
this.destroy();
this.cb = () => {
cb && cb();
this.destroy();
}
window.addEventListener('popstate', this.cb)
window.history.replaceState({ page: 'physicalBack' }, 'physicalBack');
},
destroy() {
window.removeEventListener('popstate', this.cb);
}
};
export default physicalBack;
// 使用
import physicalBack from './physicalBack'
useEffect(()=>{
physicalBack.register(()=>{console.log('physicalBack')});
return ()=>{
phyicalBack.destroy();
}
},[])