用local.hash进行页面历史管理(一)

Nov 29, 2016


​在移动端上运行WEB程序,默认情况下点返回键会返回上一个页面窗口,这个返回键可能是屏幕上的软返回键也可能是安卓三大键的返回。这样是比较方便于用户浏览的,但在体验上会出一些问题—————有时候用户并不想返回上一个页面,比如:

1.当前页面中的元素内容更新了,但并未跳到新页面,用户只是把页面内容想回到之前的状态
2.当前页面有弹出层,用户只是想关掉弹出层

这两种情况下用户点返回键的本意都不是返回上一页,但网页的实际表现是返回上一页的。从用户的体验角度来说这个网页并不善解人意,不善解人意的产品就不是好产品,一个好的产品应该是善良的,懂得体会用户在不同场景下的不同需求,然后根据这些需求去达到想要的交互。所以我们应该实现用户点击返回键时自主管理页面内容而不是简单粗暴的返回,以上都是讲给产品经理听的废话,技术实现才是坠重要的。

项目组首先想到的解决方案是监听popstate:

$(function(){ pushHistory(); window.addEventListener("popstate", function(e) { //alert("我监听到了浏览器的返回按钮事件啦");//根据自己的需求实现自己的功能 window.location = "http://www.xxxxx.com"; }, false); function pushHistory() { var state = { title: "title", url: "#" }; window.history.pushState(state, "title", "#"); } });

这个方法在安卓机上是实测有效的,但到了IOS设备上测试时,回调函数总会在莫名其妙的地方被调用,比如打开选择图片菜单的时候。在不同安卓设备上反应也不一样,查了下popstate这个属性毕竟还是比较新,可能兼容性不大好,只好另找办法了。popstate比较容易被触发,管理页面历史,还有另一个办法,那就是用url的hash值来管理。

访问一些网页的时候我们会在url末尾看到一个#接上一个字符串,这个就是页面的location.hash属性,location.hash的属性我见得多了,至少就有以下几种:

1.用来对页面的状态进行记忆以便自定义管理
2.用来进行页面的锚点定位
3.用来传递参数以避免产生过多的网络请求

这个属性可以实现如此多的功能,简直excited,但是标题上写的标号是一,所以这篇文章只会讲第一种,蛤蛤蛤蛤蛤。

我们有一个微小的需求是用户点开一张小图会出来一个弹出层,把大图展示了,这时候用户点返回键,要求关闭弹出层而不是返回上一页。

用location.hash来实现的话大概需要做三件事:

第一,把页面的初始状态设置一下 我在页面加载之初把location.hash设置为1(其实只要是一个字符串就可以了,我设置1为了方便和易懂)

图1

第二,在需要记录状态的地方,改变location.hash的值 在打开弹出层的地方,把这个值设置为2(其实只要是一个字符串就可以了,我设置为2不仅为了方便和易懂,还为了好判断)

图2

第三,监听onhashchange事件并在其中自己管理页面各元素的状态 最后,我在window.onload里面加上了onhashchange的监听。这样一旦用户点击触发到图1的代码,location.hash改变,就会进来图3这个监听回调,我在监听回调里面取出location.hash把它转成整形,然后判断一下,就可以知道现在应该做什么了,是不是too simple,but not naive?

图3

效果就是很高很赛艇,完美解决了返回键总是返回上一页面的问题。

popstate和location.hash两个都是HTML5中浏览器历史记录的API,但是区别还是有的,最后贴上一个表来说明

区别 popstate location.hash
触发条件 前进或后退按钮被点击 hash值改变
触发范围 所有同源的url 当前页面
兼容性 下图 下下图

popstate的浏览器兼容性 图4 图4

location.hash的浏览器兼容性 图5 图5

这几个表也可以接解释为什么popstate在老版本iPhone上表现很奇怪了。