自定义浏览器返回逻辑

业务场景:当某一页面有重要信息,返回操作可能会导致信息丢失或无法再回到该页面。如:用户随机抽奖,获取某实物奖品需要用户填写地址来寄送奖品,若用户返回则无法获取到获奖用户地址信息且无法再次回到填写地址的页面。

因此,类似于填写地址的页面,通常会有返回二次确认的逻辑。在APP里实现很简单,只需要订阅appbridge实例的自定义返回事件即可。但在其他APP内置浏览器和普通浏览器返回就不能拦截了。

这种情况下我们通过 history.pushState() + popstate event 的方法来实现自定义浏览器返回的需求。

关于 history.pushState

通过history.pushState() 方法可以向浏览器历史添加了一个状态。

语法 history.pushState(state, title, url); [state:状态对象,title:标题,url:新历史纪录的地址]

1
2
3
4
5
6
//向history中添加一条状态
var state = { 'page_id': 1, 'user_id': 5 };
var title = 'Hello World';
var url = 'hello-world.html';

history.pushState(state, title, url);

浏览器兼容良好,兼容情况可查看下方的 “MDN: History.pushState()详解”

MDN: History.pushState()详解

关于 popstate event

浏览器的前进后退行为(或者在JavaScript中调用history.back()、history.forward()、history.go()方法)会触发popstate事件。【注:history.pushState()或者history.replaceState()不会触发popstate事件】

语法 window.onpopstate = function() {};

1
2
3
4
5
window.onpopstate = function(event) {
console.log(JSON.stringify(event.state));
};

history.pushState({'page_id': 1}, "title 1", "?page=1"); //添加并激活一个历史记录条目

MDN: window.onpopstate详解

通过结合history.pushState()和popstate event实现自定义返回的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//向history中添加一条状态
window.onload = function() {
//调用history.pushState()方法,向history对象中添加一条状态
history.pushState({
'page_id': 1,
},'after','/after.html');
};

window.onpopstate = function(e) {
//Modal让用户选择是确定返回还是继续留在本页面
var modal = document.createElement('div');
modal.innerHTML = '<div class="content" >\
<p>文案</p>\
</div>\
<div class="btn-box">\
<a id="btn-cancel"class="btn btn-cancel" href="javascript: void(0)">取消</a>\
<a id="btn-confirm" class="btn btn-confirm" href="javascript: void(0)">确定</a>\
</div>';
document.body.appendChild(modal);
var cancelBtn = document.getElementById('btn-cancel');
var confirmBtn = document.getElementById('btn-confirm');

cancelBtn.onclick = function() {
history.pushState({
'page_id': 1,
},'after','/after.html');
document.body.removeChild(modal);
};
confirmBtn.onclick = function() {
history.go(-1);
document.body.removeChild(modal);
};
};

点击查看实现效果http://5.zhangjinxin.applinzi.com/before.html