ajax与HTML5 history pushState/replaceState实例

这篇文章发布于 2013年06月19日,星期三,20:47,归类于 JS实例。 阅读 325999 次, 今日 17 次 77 条评论

 

一、本文就是个实例展示

三点:

  1. 我就TM想找个例子,知道如何个使用,使用语法什么的滚粗
  2. 跟搜索引擎搞基
  3. 自己备忘

精力总是有限的,昨天一冲动,在上海浦东外环之外订了个90米的房子,要借钱筹首付、贷款和领证什么的。HTML5 history相关知识点啪啦啪啦讲起来也是一条又臭又长的裹脚布,精气神实在不够用,这里,直接一个实例。

二、ajax载入与浏览器历史的前进与后退

众所周知,Ajax可以实现页面的无刷新操作——优点;但是,也会造成另外的问题,无法前进与后退!曾几何时,Gmail似乎借助iframe搞定,如今,HTML5让事情变得如同过家家般简单。

当执行Ajax操作的时候,往浏览器history中塞入一个地址(使用pushState)(这是无刷新的);于是,返回的时候,通过URL或其他传参,我们就可以还原到Ajax之前的模样。

本demo所展示的就是ajax的内容载入与地址栏的前进与后退,典型应用,对于熟悉相关知识点很有帮助。

三、demo实例

您可以狠狠地点击这里:HTML5 history API与ajax分页实例

demo结构大致如下:左边导航菜单,右侧详细内容。
demo页面大致结构

如果我们想偷懒,导航直接URL地址,点击刷新得了。但头尾内容都是一样的,刷新总显得浪费。从体验上讲,点击导航,右侧Ajax局部刷新是更优的策略。

Ajax局部刷新小菜,稍有经验都能轻松应对。现在如果提出如下需求:每次ajax刷新就如果页面刷新一样,可以后退查看之前内容,怎么破?

我的策略如下:

  • 每次手动点击左侧的菜单,我将Ajax地址的查询内容(?后面的)附在demo HTML页面地址后面,使用history.pushState塞到浏览器历史中。
  • 浏览器的前进与后退,会触发window.onpopstate事件,通过绑定popstate事件,就可以根据当前URL地址中的查询内容让对应的菜单执行Ajax载入,实现Ajax的前进与后退效果。
  • 页面首次载入的时候,如果没有查询地址、或查询地址不匹配,则使用第一个菜单的Ajax地址的查询内容,并使用history.replaceState更改当前的浏览器历史,然后触发Ajax操作。

于是,你会看到:

  • 页面首次载入,虽然我们访问的URL的后缀是光秃秃的.html,但是,实际URL最后是:
    首次载入页面的URL

    因为被history.replaceState摆了一道。

  • 鼠标点击左边的任意一个菜单,会发现,右侧内容虽然是Ajax载入,但是,页面的URL地址却变了,例如,点击宝山区:
    点击宝山区URL地址变化

    因为历史记录被history.pushState插了一刀。

  • 此时,我们点击地址栏的后退按钮,就是这个:
    点击后退、查看历史记录

    奇迹般的,页面无刷新的,又回到了浦东菜单:
    回到了浦东,同时出现了历史前进按钮

    因为window.onpopstate让菊花刀又拔了出来。

四、其它点什么

  • history.pushState
    菊花插一刀之意,用法举例:

    history.pushState({}, "页面标题", "xxx.html");
  • history.replaceState
    换把菊花刀之意,用法举例:

    history.replaceState(null, "页面标题", "xxx.html");
  • window.onpopstate
    在菊花刀拔插的时候……,用法举例:

    window.addEventListener("popstate", function() {
        var currentState = history.state;
        /*
         * 该干嘛干嘛
        */
    });

浏览器兼容性表:

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari
replaceState, pushState 5 4.0 (2.0) 10 11.50 5.0
history.state 18 4.0 (2.0) 10 11.50 6.0

恩,就这些!

补充于2013-06-20
@滴洋在评论中提到pjax. 那pjax是什么呢?

pjax是一种基于ajax+history.pushState的新技术,该技术可以无刷新改变页面的内容,并且可以改变页面的URL。pjax是ajax+pushState的封装,同时支持本地存储、动画等多种功能。目前支持jquery、qwrap、kissy等多种版本。

李小龙

呀!打~~!!~~骚年,还不亮出你的菊花·········································刀!

(本篇完)

分享到:


发表评论(目前77 条评论)

  1. jiabing说道:

    7年后,我才来看这个,我TM真够菜的

  2. 大菜鸡说道:

    做了一年前端才知道这个玩意

  3. null说道:

    还有什么是在这里找不到的?

  4. mn说道:

    俺也一样

  5. lxd说道:

    如果是上个页面中有很多异步请求,而且有的异步请求是在某个异步请求基础上点击某个事件异步的,这种情况如何点击回退到这页面,也依然要和这个页面的效果一样,可以怎么去实现呢?

    • 张 鑫旭说道:

      这么啰嗦,都没看明白你的问题,显然,需要重新调整设计,从设计源头解决这个问题,这个设计指的是交互设计。

  6. 1zheng说道:

    2013年06月19日发布的文章,我现在才看到,我也是醉了

  7. 王天说道:

    大神,你好,我现在写的页面间跳转出现死循环了,该怎么解决,谢谢啦

  8. 想暴富的妞儿说道:

    location.href.split(“#”)[0] + “?” + eleTarget.href.split(“?”)[1]) + location.hash;
    不明白为什么这里是#呢?
    不是问号吗?

  9. 再长好看一点就好了说道:

    history.replaceState(null, document.title, location.href.split(“#”)[0] + “?” + eleTarget.href.split(“?”)[1]) + location.hash; 这里为什么要加个location.hash ??没明白,手动在浏览器下也敲了一边还是不明白 指点一下

  10. ssy说道:

    有demo的github地址吗?

  11. icon说道:

    pushstate的话页面会有缓存吗?

  12. 说道:

    写的太棒了。 遇到了这个history的问题,通过看你的文章找到了思路。

    我看了你的代码,使用html?xxxx 中解析出页面。 每次解析似乎比较麻烦,
    我直接把ajax div对应的url存入state变量,中,这样不需要每次都解析!!

    http://blog.csdn.net/taiji1985/article/details/79296814

  13. 几句话说道:

    这个文章的说明还算清晰, 就是没有直接上代码…如果有代码就更清晰了..

  14. lxt410725说道:

    刚开始学习 demo不能下载。能传到github上吗?

  15. Eden说道:

    学习了

  16. 想知道答案的人说道:

    大神,在新闻列表页面,下拉到指定位置用ajax动态添加了数据,点击了一条数据后,跳到详情页面,然后返回,跳到的页面,动态添加的数据都消失了,有没有什么方法可以解决

    • 小叶子说道:

      你这样问,说明你这个例子还是没吃透,你可以把浦东区栏目下的浦发御园楼盘设置成a链接试试。然后你说的 “下拉到指定位置用ajax动态添加了数据” 等同于此例中的点击栏目加载数据。

  17. zero说道:

    在ios上可以用吗

  18. Hbx说道:

    学习了,与hash、hashchange一样好玩儿

  19. 搜记网说道:

    谢谢分享,我有个疑问,你在history.replaceState处,后面加个+ location.hash; 有什么用途?

  20. fugel说道:

    嗯嗯,学习啦

  21. 馨恋网说道:

    太好了 非常谢谢楼主的教程。能提供demo下载更好

  22. 郑晓说道:

    这个 请求数据 只能用get吗

  23. 起阳说道:

    感谢楼主,正在写单页,找了很多教程,就你的这个最好。万分感谢楼主分享

  24. pushState说道:

    你好

  25. LJ说道:

    用了history.pushState就应该把AJAX请求的所有参数放进stateObject里面啊,
    你这样的做法不还是刀耕火种时期的用hash做法,直接#后面加参数就行啦。
    楼主是不理解histroy.pushState出现的价值。

    • sadkilo说道:

      刀耕火种时期的用hash做法时, 页面会刷新,而用histroy.pushState 页面不会刷新, 另外histroy.pushState还有其他价值?

    • fddv说道:

      想如果用户加了收藏夹。。。什么stateObject全丢掉。。。明明我转的是菊花地址怎么回到了首页?

  26. 一土说道:

    正好需要,大赞楼主

  27. Kuma说道:

    这个属性用在移动端app上,安卓上可以插入历史记录,但是IOS好像没啥反应。
    这个有啥解决的办法么?

  28. 刘易斯说道:

    旭哥好!我写个简单代码测试pop事件的触发,发现从“无关页面”返回最后一个push页面没有触发事件,而你的例子中从“回到相关文章”页面返回时,却正常显示最后的查询。
    =================测试如下===============

    history.replaceState({x:1},’x1′,’?a=1′);
    history.pushState({x:1},’x2′,’?a=2′);
    history.pushState({x:1},’x3′,’?a=3′);
    window.addEventListener( “popstate”, function(e) { alert(e.state.x); } );

    无关页面,测试后退是否触发事件
    ===============请教旭哥该事件发生的条件=======================

  29. Xinuy说道:

    菊花的故事。太逗了哈哈

  30. 小庄说道:

    请问后端php要怎么处理啊 ???

  31. zdz说道:

    大大 我最近也遇到这个问题 使用了插件pjax 但是却没作用
    直接就跳转这个页面了 不知道你后端是怎么处理的 可以发个源码吗 谢谢了

  32. 说道:

    博主你好, 既然你是拿ajax请求的,那么像这些地址栏问号 后面的参数在后台都有相应的处理吗? http://www.zhangxinxu.com/study/201306/ajax-page-html5-history-api.html?area=huangpu

    要不然我保存这个url 为书签,下次我从书签点击请求,而请求这个url 你后台怎么知道是前端哪个界面呢?要不然只返回数据,没有样式啊??

  33. scotttt说道:

    还有哈 这html5的特性 我直接在本地html页面不能运行 非得挂在iis上才有效果呢

  34. scotttt说道:

    pjax 好厉害呀 话说楼主 你这上海的房价几何啊?

  35. 小荄说道:

    厉害呀,不过问下用这个history API能否取到上一个页面的url,就相当于HTML4中 document.referrer这个功能~~

  36. 柠檬说道:

    感觉有点不完美,是模拟出来的后退;
    首次点击后退按钮的时候,刚开始点击的比较快,一直是同一个页面内容。原来又重新发了次请求,是内容没有返回来。再次点击的时候页面后退和前进响应就很快了

  37. 小媒体软件说道:

    太好的文章了,收藏了!

  38. 熊猫说道:

    这种方式可以使搜索引擎抓取到ajax的内容么

    • 毅恒说道:

      由于使用了问号而不是井号,每个链接地址对搜索引擎都是唯一的,当然会被抓取

  39. blues说道:

    博主13年6月买的房,现在应该涨了20%了吧?嘿嘿

  40. jason.Huang说道:

    一如既往地生动形象,学习了

  41. 秋水梦道说道:

    以菊花作比push、pop,真是恰当啊。。。风趣的博主

  42. 红色石头说道:

    我也看了很多这个东西~~~http://50vip.com/blog.php?i=355

  43. pardus说道:

    为什么在执行后退时,只能执行一步,再点击‘后退’,始终查询当前的地址内容?

  44. 青豆说道:

    这个方法当执行html5全屏(FullScreen)的时候,ajax,pushState改变url的时候,会退出全屏。不知道有解决方案吗?(在chrome下会,但是在Firefox下却没问题),就是实现houzz.com全屏图片效果。

  45. 冰河遗民说道:

    看的不是太明白,貌似很厉害的样子。好歹也学了近3个月前端了,看这个还是太费脑筋,作者说的不错,纯粹是为了备忘!

  46. 善良的笨狼说道:

    大哥, pushState里的参数只是最后一个url有用,其他都是摆设是吧,为啥我搞了一个,点后退只是地址改变,内容没改变,知道大概什么原因么

    • 张 鑫旭说道:

      @善良的笨狼 应该是没有绑定popstate事件。

      • 善良的笨狼说道:

        不好意思一大早没睡醒,刚点错回复
        window.onpopstate = popState;
        function popState(event) {
        if (history.state) {
        $(‘#J-article-list’).html(history.state.html);
        //关于state我这样的做法好像比较屌丝,我看微博的都没向state里填东西,大哥你的传了
        也只是放在里面,都没用到,这是为啥
        }
        }

      • 善良的笨狼说道:

        那state里面的内容,跟页面的内用有啥关系啊,微博里的state一直都是null,一样切换自如,这个关键点在哪哦,求大侠指教

  47. Feelop说道:

    不可用 -.-
    直接跳轉了
    chrome和FF測試

  48. cssmagic说道:

    有笔误,“换把菊花刀之意,用法举例”这一小节的小标题应该是“history.replaceState”。

  49. 滴洋说道:

    这就是传说中的PJAX!