业务场景:
用户没有填完数据却不小心点到了回退按钮,此时需要展示确认弹框
项目场景:
vue2 + uni-app + Chrome Dev调试工具
代码片段:
onLoad(options){
// 将当前url地址添加到浏览器的历史记录中
window.history.pushState(null, null, document.URL);//第三个参数不写默认为当前url地址
// 监听物理返回
window.addEventListener('popstate', this.listenBack, false);
}
destroyed(){ //也可用 beforeDestroy 、onUnload 代替
// 页面销毁前取消上一次的监听
window.removeEventListener('popstate', this.listenBack, false);
},
methods:{
// 物理返回的操作函数
listenBack() {
// 此处state仅作参考
if (this.state === '未保存') {
uni.showModal({
title: '提示',
content: '内容还未保存,是否退出',
success: (res) => {
if (res.confirm) {
console.log('用户点击确定');
//此处可写人一些用于保存页面信息的代码……
//因为在onLoad中中多存储了一个历史记录,所以这里要返回上上个页面
history.go(-2);
} else if (res.cancel) {
console.log('用户点击取消');
//等待用户接着操作……
}
}
});
}else{
history.go(-2)
}
}
}
思路分析:
其实这个需求的难点在于:监听到了物理返回,但是会先执行当前vue页面的destroyed函数,再执行物理返回中的操作函数。这样就会导致页面已经跳回上一个页面后才出现提示框。
于是我的做法是:在当前vue页面(A页面)加载时往浏览器历史里备份一份当前的url地址(B页面),此时用户点击返回,就会从B页面跳到A页面,由于这两个页面地址一致,就会产生点击回退却没有效果的错觉。接着回到A页面后,触发监听事件,处理具体的业务流程……
其他方法:
1.如果不需要监听物理返回,而是监听uni-app自带的左上角的返回键。可以使用uni的生命周期函数 onBackPress
2.除了onpopstate可以监听页面回退外,还可以使用window.onhashchange监听hash路由变化。
3.也可以用vue-router中的 beforeRouteLeave 监听路由变化。但是我项目中使用没生效,就没用这种方法。
无用的小技巧:
如果想禁用一个页面的返回操作,只需要在这个页面的历史记录中写入大量的历史。比如:
for(var i = 0 ; i < 20 ; i++){
history.pushState(null,null)
}
相对的,取消禁用就需要以下代码 + 一个手动回退
history.go(-20)
location.reload()
参考文献: