前言
1.主要是返回是默认的浏览器返回事件是返回上一个页面。html
2.处理页面各类弹窗,点击物理返回应该隐藏这些弹窗而不是直接返回页面。vue
3.总结下问题,h5应该但愿能监听到返回事件而且作一些处理。react
一、利用popstate
事件,点击浏览器前进,后退会触发popstate事件。浏览器
二、利用hashchange
事件,页面hash改变是会触发此事件(适合react,vue单页面应用)。bash
每当处于激活状态的历史记录条目发生变化时,popstate
事件就会在对应window
对象上触发. 若是当前处于激活状态的历史记录条目是由history.pushState()
方法建立,或者由history.replaceState()方法修改过
的, 则popstate事件对象的state
属性包含了这个历史记录条目的state对象的一个拷贝.函数调用
history.pushState()
或者history.replaceState()
不会触发popstate事件.popstate
事件只会在浏览器某些行为下触发, 好比点击后退、前进按钮(或者在JavaScript中调用history.back()、history.forward()、history.go()
方法).性能
history.pushState()
不会刷新页面,往历史记录中添加一条记录。优化
history.replaceState()
不会刷新页面,替换当前页面记录,不会在历史记录中新增。ui兼容性:当网页加载时,各浏览器对
popstate
事件是否触发有不一样的表现,Chrome 和 Safari会触发popstate
事件, 而Firefox不会.this
假如当前网页地址为example.com/example.htm…,则运行下述代码后:
window.onpopstate = () => {} 等同于 window.addEventListener('popstate',() => {});
window.onpopstate = function(event) {
alert("location: " + document.location + ", state: " + JSON.stringify(event.state));
};
//绑定事件处理函数.
history.pushState({page: 1}, "title 1", "?page=1"); //添加并激活一个历史记录条目 http://example.com/example.html?page=1,条目索引为1 当前记录有两条记录(包括最开始的)
history.pushState({page: 2}, "title 2", "?page=2"); //添加并激活一个历史记录条目 http://example.com/example.html?page=2,条目索引为2 当前记录有三条记录
history.replaceState({page: 3}, "title 3", "?page=3"); //修改当前激活的历史记录条目 http://ex..?page=2 变为 http://ex..?page=3,条目索引为3 当前记录有三条(replaceState会替换第三条条)
history.back(); // 弹出 "location: http://example.com/example.html?page=1, state: {"page":1}"
history.back(); // 弹出 "location: http://example.com/example.html, state: null history.go(2); // 弹出 "location: http://example.com/example.html?page=3, state: {"page":3}
复制代码
如上图,假设当前页面是A页面,跳转到B页面,B页面打开dialong弹窗,这个时候点击返回,默认是返回到A页面。这种体验是不好的,优化体验,这个时候须要优化这种体验性能问题。
场景:在B页面中有个弹窗,点击返回,要关闭弹窗,再次点击,返回到A页面。
代码以下:
// 假设A页面为http://www.example.com/a.html
// B页面是http://www.example.com/b.html
// 下面以react生命周期为例
componentDidMount: function() {
window.addEventListener('popstate',(state) => {
// 监听到返回事件,注意,只有触发了返回才会执行这个方法
console.log(state);
this.back();
})
}
// 假设点击打开对话窗,利用pushState添加一天记录
openDialong: function() {
// 此时页面地址为b.html?page=1,可是页面没有刷新。而且不会触发popstate方法
history.pushState({page: 1}, "title 1", "?page=1");
// TODO
}
// 弹窗已存在,而且点击了返回事件,此时页面b.html?page=1--->b.html,并触发popstate事件
back: function() {
// 页面在用户看来是没有刷新的,此时是关闭dialong
// TODO
}
// 离开页面的时候取消监听popstate
componentWillUnmount: function() {
window.removeEventListener('popstate',(state) => {
this.back();
})
}复制代码
当 一个窗口的 hash (URL 中 # 后面的部分)改变时就会触发 hashchange 事件(参见
location.hash
)。if ("onhashchange" in window) { alert("该浏览器支持 hashchange 事件!"); } function locationHashChanged() { if (location.hash === "#somecoolfeature") { somecoolfeature(); } } window.onhashchange = locationHashChanged;复制代码
仍是以上面场景为例:
// 假设A页面为http://www.example.com/a.html#/a
// B页面是http://www.example.com/a.html#/b
// 下面以react生命周期为例
componentDidMount: function() {
window.addEventListener('hashchange',(state) => {
// hash改变就会触发
const href = location.href;
// 当前hash中不存在?page=1是触发(初始化刚进来是不会触发这个方法的)
if (href.indexOf('?page=1') < 0) {
this.back();
}
})
}
// 假设点击打开对话窗,利用pushState添加一天记录
openDialong: function() {
// 此时页面地址为a.html?page=1,可是页面没有刷新。而且不会触发popstate方法
// history.pushState({page: 1}, "title 1", "?page=1");
// 不过此时会触发hashchange,可是加个判断;
this.props.history.push('/b?page=1');
// TODO
}
// 弹窗已存在,而且点击了返回事件,此时页面a.html?page=1--->a.html,并触发hashchange事件
back: function() {
// 页面在用户看来是没有刷新的,此时是关闭dialong
// TODO
}
// 离开页面的时候取消监听hashchange
componentWillUnmount: function() {
window.removeEventListener('hashchange',(state) => {
this.back();
})
}
复制代码
仍是这个图片
假设A是首页,B详情页面,C是支付页面,D是结果页面。(咱们但愿D不能返回到C页面)。
假设要从D页面跳转到B页面(B,C,D也同样), 从结果页面D中点击按钮跳转到详情B页面,可再次购买。
有如下方法:
方法一:location.href = 'http://www.example/b.html';
方法二:history.go(-2);复制代码
主要区别:
方法一会往历史记录中添加新的记录,变成A—>B—>C—>D—>B。
此时点击物理返回,就会回到D页面。而这不是咱们要的结果。
方法二是回到历史记录中,不会新增记录,链路仍是A—>B—>C—>D。
D页面不该该回到C页面
此时咱们就能够用到上面的方法,点击返回利用history.go()的方法,回到咱们想到的页面。
// D页面---->B页面
componentDidMount: function() {
this.props.history.push('/b?page=1');
// 若是有问题,加个setTimeout
window.addEventListener('hashchange',(state) => {
// hash改变就会触发
const href = location.href;
// 当前hash中不存在?page=1是触发(初始化刚进来是不会触发这个方法的)
if (href.indexOf('?page=1') < 0) {
this.back();
}
})
}
// 而且点击了返回事件,此时页面d.html?page=1--->d.html,并触发hashchange事件
back: function() {
// 页面在用户看来是没有刷新的,此时是回到B页面
// TODO
this.props.history.go(-2);
}
// 离开页面的时候取消监听hashchange
componentWillUnmount: function() {
window.removeEventListener('hashchange',(state) => {
this.back();
})
}复制代码
有问题欢迎指正。