前言:最近在做项目的过程中,做到与搜索引擎相关的问题, 当搜索一个关键词时, 我们通过ajax请求获取到数据,然后填充到当前页面,这样做的好处是可以实现页面的无刷新操作,但是ajax请求存在一个问题 --- 在浏览器中无法前进和后退!!
导致的问题: 这样,如果用户希望下次可以返回到之前的浏览记录就是不可能的了,这样用户体验会大大下降。
最终目的: 我们希望做到的就是: 每次的ajax请求可以存到历史中去,这样,用户就可以在浏览器中通过前进和后退按钮来查看浏览过的历史了。
解决思路: 曾经,google的做法是使用iframe来解决这样的问题,即模仿页面没有被刷新的状态,这样就可以使用前进和后退按钮了。但是HTML5出来之后,解决问题就会轻松很多了 --- ajax无前进和后退的本质是历史记录不会保存,所以我们可以利用html5的方法 pushState 强行给浏览器添加一个历史记录, 然后再点击前进和后退的时候通过给url传参的形式就可以返回到之前pushState的历史记录中了。 这个方法妙啊!
争议: 有人说了: 我可以每次在查询的时候不使用ajax请求,而是导航到一个新页面,这样不就成功的规避了ajax请求没有自行保存历史记录的问题了吗?
回答: 这个思路是没有问题的,但是试想,每次再我们搜索的时候,我们只是希望改变内容部分, 而不需要重新刷新整个页面(包括header和footer)。如果使用导航到新页面,就不可避免的导致刷新整个页面造成资源浪费。
解决方法:
1. 在搜索栏中输入关键词并点击搜索按钮后, 就将ajax查询的内容附在url的?之后作为查询字符串, 然后再使用history.pushState即可将当前的“独一无二”的url保存在历史记录中。
2. 当我们点击浏览器的返回按钮时,或者执行相应的返回操作时,就会触发 window.onpopstate 事件, 通过绑定popstate事件,我们就可以再将历史中的查询字符串中的之前ajax查询的内容使用js提取出来然后再执行ajax载入,这个载入是不需要使用window.pushState的,否则就会进入死循环,通过这种方式我们就可以模仿实现返回的效果。对于前进也是一样的思路。
3. 当页面首次载入的时候,如果没有查询地址或者查询地址不匹配,则使用第一个菜单的Ajax地址的查询内容,并使用history.replaceState
更改当前的浏览器历史,然后触发Ajax操作。 注: 这个方法可能在某些内容必须有的情况下是这样的,但是对于我目前的项目而言, 这个histoty.replaceState似乎并没有太大的必要,准确的说是不需要。
使用方法:
1.history.pushState
history.pushState({}, "页面标题", "xxx.html");
var state = { title: title, url: options.url, otherkey: othervalue};window.history.pushState(state, document.title, url);
2.history.replaceState
history.replaceState(null, "页面标题", "xxx.html");
3.window.onpopstate
window.addEventListener("popstate", function() {
var currentState = history.state;
/*
* 干点啥 */ }); 4. history.state 当前URL下对应的状态信息。如果当前URL不是通过pushState或者replaceState产生的,那么history.state是null。 我们直接打开console控制台, 然后输入history.state得到的就是null,因为我们还没有利用pushState和replaceState。
参考文章: