ajax与HTML5 history pushState/replaceState实例

一、本文就是个实例展示

三点:

  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.pushStatehistory.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等多种版本。

李小龙

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

(本篇完)

分享到:

标签: , , , , , ,

赞助商推荐(我也要赞助)

想学到点真东西? ×
如果你有1~3年前端开发经验,不妨 ×


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

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

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

  2. zero说道:

    在ios上可以用吗

  3. Hbx说道:

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

  4. 搜记网说道:

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

  5. fugel说道:

    嗯嗯,学习啦

  6. 馨恋网说道:

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

  7. 郑晓说道:

    这个 请求数据 只能用get吗

  8. 起阳说道:

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

  9. pushState说道:

    你好

  10. LJ说道:

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

    • sadkilo说道:

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

  11. 一土说道:

    正好需要,大赞楼主

  12. Kuma说道:

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

  13. 刘易斯说道:

    旭哥好!我写个简单代码测试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); } );

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

  14. Xinuy说道:

    菊花的故事。太逗了哈哈

  15. 小庄说道:

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

  16. zdz说道:

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

  17. 说道:

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

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

  18. scotttt说道:

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

  19. scotttt说道:

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

  20. 小荄说道:

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

  21. 柠檬说道:

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

  22. 小媒体软件说道:

    太好的文章了,收藏了!

  23. 熊猫说道:

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

    • 毅恒说道:

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

  24. blues说道:

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

  25. jason.Huang说道:

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

  26. 秋水梦道说道:

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

  27. 红色石头说道:

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

  28. pardus说道:

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

  29. 青豆说道:

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

  30. 冰河遗民说道:

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

  31. 善良的笨狼说道:

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

    • 张 鑫旭说道:

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

      • 善良的笨狼说道:

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

      • 善良的笨狼说道:

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

  32. Feelop说道:

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

  33. cssmagic说道:

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

  34. 滴洋说道:

    这就是传说中的PJAX!