HTML5 history

引入history.pushState的来龙去脉

大家都知道web2.0以来,大家都喜欢使用ajax来请求数据,提高用户体验,但是传统的ajax可以无刷新改变页面内容,但无法改变页面URL,无刷新的改变页面内容而url没有改变导致搜索引擎无法抓取改变的页面内容。

为了提高可访问性,大家想了各种方法,比如说改变URL的hash,但是hash的方式不能很好的处理浏览器的前进、后退,为了能够区分不同的hash,浏览器引入了onhashchange事件,但并在所有浏览器都支持onhashchange,对于不支持onhashchange事件的浏览器只能通过定时去判断hash是否改变,而且搜索引擎不会理会井号,因此也就无法索引内容,这种方式显然不够灵活。

为此twitter和google约定了使用#!xxx(即hash第一个字符为!),引用了新的方式#!之后搜索引擎必须加以支持,比如说网址是http://example.com#!1,当搜索引擎发现上述网址是会自动解析成http://example.com?_escaped_fragment_=1,但是这种方式对用户来说使用起来相当麻烦。

这时HTML5为了解决传统ajax带来的问题引入了新的API,即:history.pushState, history.replaceState

history.pushState

pushState是将指定的URL添加到浏览器历史里,存储当前历史记录点

API:history.pushState(state, title, url)

  1. // @state状态对象:记录历史记录点的额外对象,可以为空
  2. // @title页面标题:目前所有浏览器都不支持
  3. // @url可选的url:浏览器不会检查url是否存在,只改变url,url必须同域,不能跨域

history.pushState的目的

  • SEO优化
  • 更少的数据请求
  • 更好的用户体验

history.replaceState

replaceState是将指定的URL替换当前的URL,替换当前历史记录点

replaceState的api和pushState类似,不同之处在于replaceState不会在window.history里新增历史记录点,而pushState会在历史记录点里新增一个记录点的

history.state

当前URL下对应的状态信息。如果当前URL不是通过pushState或者replaceState产生的,那么history.state是null。

state对象虽然可以存储很多自定义的属性,但对于不可序列化的对象则不能存储

window.onpopstate事件

window.onpopstate事件主要是监听历史记录点,也就是说监听URL的变化,但会忽略URL的hash部分。

history.go和history.back(包括用户按浏览器历史前进后退按钮)触发,并且页面无刷的时候(由于使用pushState修改了history)会触发popstate事件,事件发生时浏览器会从history中取出URL和对应的state对象替换当前的URL和history.state。通过event.state也可以获取history.state

注意点:

  1. javascript脚本执行window.history.pushState和window.history.replaceState不会触发onpopstate事件。
  2. 谷歌浏览器和火狐浏览器在页面第一次打开的反应是不同的,谷歌浏览器奇怪的是回触发onpopstate事件,而火狐浏览器则不会。

实例Demo

页面css如下:

 body {
            overflow-x: hidden;
        }
        ul {
            padding: 0;
            margin: 0;
            list-style-type: none;
        }
        .header {
            font-weight: 18px;
            color: red;
            height: 100px;
            line-height: 100px;
            text-align: center;
        }
        .cho_link {
            background: url(../image/choose_bg.png) no-repeat;
        }

        .cho_search {
            width: 170px;
            margin-right: -20px;
            padding-right: 20px;
            *vertical-align: -2px;
        }

        .cho_box {
            border: 1px solid #bfbfbf;
            background-color: #ebebeb;
            *position: relative;
            overflow-y: hidden;
        }

        .cho_line {
            display: block;
            padding-top: 2px;
            background-color: #d2d2d2;
            border-bottom: 1px solid #f0f0f0;
        }

        .cho_left {
            width: 20%;
            margin-right: 10px;
            float: left;
            position: relative;
        }

        .cho_menu {
            padding-bottom: 72px;
            padding-top: 1px;
        }

        .cho_link, .cho_link_on {
            display: block;
            line-height: 32px;
            padding-left: 19px;
            color: #333;
            *zoom: 1;
        }

        .cho_link {
            background-color: #fafafa;
            border-bottom: 1px solid #f6f6f6;
            outline: none;
        }

            .cho_link:hover {
                background: #f6f6f6;
                border-bottom: 1px solid #e0e0e0;
                text-decoration: none;
            }

        .cho_link_on {
            margin: -1px -1px 0 0;
            background: #ebebeb;
            border-bottom: 1px solid #ccc;
            border-top: 1px solid #ccc;
            position: relative;
            cursor: default;
        }

            .cho_link_on:first-child {
                border-top: 0;
            }

            .cho_link_on:hover {
                text-decoration: none;
            }

页面html代码:

<div class="header">head</div>
    <div class="center">
        <!-- 左边的选菜项 -->
        <div class="cho_left">
            <ul id="choMenu" class="rel cho_menu">
                <li><a href="ajax.aspx?area=pudong" class="cho_link cho_link_on">浦东区</a></li>
                <li><a href="ajax.aspx?area=baoshan" class="cho_link">宝山区</a></li>
                <li><a href="ajax.aspx?area=jiading" class="cho_link ">嘉定区</a></li>
                <li><a href="ajax.aspx?area=qingpu" class="cho_link">青浦区</a></li>
                <li><a href="ajax.aspx?area=minhang" class="cho_link">闵行区</a></li>
                <li><a href="ajax.aspx?area=putuo" class="cho_link">普陀区</a></li>
                <li><a href="ajax.aspx?area=jinshan" class="cho_link">金山区</a></li>
                <li><a href="ajax.aspx?area=songjiang" class="cho_link">松江区</a></li>
                <li><a href="ajax.aspx?area=zhabei" class="cho_link">闸北区</a></li>
                <li><a href="ajax.aspx?area=fengxian" class="cho_link">奉贤区</a></li>
                <li><a href="ajax.aspx?area=huangpu" class="cho_link">黄浦区</li>
                <li><a href="ajax.aspx?area=changning" class="cho_link">长宁区</a></li>
                <li><a href="ajax.aspx?area=jingan" class="cho_link">静安区</a></li>
                <li><a href="ajax.aspx?area=zhoubian" class="cho_link">上海周边</a></li>
            </ul>
        </div>

        <!-- 右侧主列表 -->
        <div class="cell">
            <div id="listBox">
                右侧显示相应的内容
            </div>
        </div>
    </div>
    <div class="header">footer</div>

JS代码:

//给每个左侧链接绑定事件
        var eleMenus = $("#choMenu a").bind("click", function (event) {
            //获得querystring的值
            var query = this.href.split("?")[1];
            //将左侧列表链接全部去掉高亮
            $("#choMenu a").removeClass(‘cho_link_on‘);
            //给当前点击的链接加高亮
            $(this).addClass(‘cho_link_on‘);
            //如果存在history.pushState状态  且有queryString的值
            if (history.pushState && query) {
                var curText = $(this).text();
                //给右侧内容框赋值
                $(‘#listBox‘).text(curText);
                // history处理

                document.title = "history demo-" + curText;
                if (event && /\d/.test(event.button)) {
                    //history.pushState使得页面的URL地址变化了
                    history.pushState({ title: title }, title, location.href.split("?")[0] + "?" + query);
                }
            }
            return false;
        });

        var fnHashTrigger = function (target) {
            var query = location.href.split("?")[1], eleTarget = target || null;
            //页面首次载入,没有queryString的值
            if (typeof query == "undefined") {
                if (eleTarget = eleMenus.get(0)) {
                    // 如果没有查询字符,则使用第一个导航元素的查询字符内容
                    history.replaceState(null, document.title, location.href.split("#")[0] + "?" + eleTarget.href.split("?")[1]) + location.hash;
                    fnHashTrigger(eleTarget);
                }
            } else {
                eleMenus.each(function () {
                    if (eleTarget === null && this.href.split("?")[1] === query) {
                        eleTarget = this;
                    }
                });

                if (!eleTarget) {
                    // 如果查询序列没有对应的导航菜单,去除查询然后执行回调
                    history.replaceState(null, document.title, location.href.split("?")[0]);
                    fnHashTrigger();
                } else {
                    $(eleTarget).trigger("click");
                }
            }
        };

        if (history.pushState) {
            //页面无刷新的,原先ajax请求的数据加载过来了  这就是popstate事件的作用
            window.addEventListener("popstate", function () {
                fnHashTrigger();
            });

            // 默认载入
            fnHashTrigger();
        }

代码大家可以复制过去自己试一下,代码实现的功能是页面的跳转(前进后退,点击等)不重新请求页面,但是会相应改变右侧区域的内容且url改变了,而且可以通过无刷新的请求回退状态,真的是无限级的提高了用户友好性。

浏览器支持情况

时间: 2024-10-04 18:39:48

HTML5 history的相关文章

ajax与HTML5 history pushState/replaceState实例

一.本文就是个实例展示 三点: 我就TM想找个例子,知道如何个使用,使用语法什么的滚粗 跟搜索引擎搞基 自己备忘 精力总是有限的,昨天一冲动,在上海浦东外环之外订了个90米的房子,要借钱筹首付.贷款和领证什么的.HTML5 history相关知识点啪啦啪啦讲起来也是一条又臭又长的裹脚布,精气神实在不够用,这里,直接一个实例. 二.ajax载入与浏览器历史的前进与后退 众所周知,Ajax可以实现页面的无刷新操作——优点:但是,也会造成另外的问题,无法前进与后退!曾几何时,Gmail似乎借助ifra

HTML5 History API

以Html5 History API为关键词搜索,会得到很多结果,我仅根据自己的使用整理. 1.两个API pushState和replaceState. pushState向浏览器历史记录里增加一个状态,供浏览器后退前进时使用,用法 history.pushState(data, '页面标题', url); replaceState就是替换某个状态,参数和pushState一样. 2.一个事件 onpopstate. 用户点击了前进或者后退就会触发,而不是使用pushState或者replac

HTML5 History对象,Javascript修改地址栏而不刷新页面(二)

一.实例说明: $('#btnOne').click(function () { var stateObject = { id: 1 }; var title = "本地首页"; var newUrl = '/index.html'; //修改地址栏中的地址 /* * 使用说明,pushState中缓存的地址,必须是当前域中的地址 */ history.pushState(stateObject, title, newUrl); }); $('#btnTwo').click(funct

html5 - history 历史管理

参考文章: w3c     :  http://www.w3.org/html/ig/zh/wiki/HTML5/history 张鑫旭  : http://www.zhangxinxu.com/wordpress/2013/06/html5-history-api-pushstate-replacestate-ajax/ zawa   :  http://zawa.iteye.com/blog/1271031 Demo : Demo 截图: 代码: <!DOCTYPE html PUBLIC

使用 HTML5 History 新特性增强 Ajax 的体验(转)

一. 场景再现 如大家熟知,Ajax 可以实现页面的无刷新操作,但会造成两个与普通页面操作(有刷新地改变页面)有着明显差别的问题—— URL 没有修改以及无法使用前进.后退按钮.例如常见的 Ajax 分页,在第一页点击第二页的链接,Ajax 分页完成后浏览器地址栏上显示的 URL 依然是第一页的 URL,使用后退按钮也无法回到第一页.url 的改变代表一个标识,在传统的网页体验中,内容的变更伴随 url 的改变,url 的改变.前进和后退按钮三者之间更加形成一种独特的导航体验,而 Ajax 破坏

转:HTML5 History API 详解

从Ajax翻页的问题说起 请想象你正在看一个视频下面的评论,在翻到十几页的时候,你发现一个写得稍长,但非常有趣的评论.正当你想要停下滚轮细看的时候,手残按到了F5.然后,页面刷新了,评论又回到了第一页,所以你又要重新翻一次. 再或者,你想把这个评论发给别人分享,一面给了别人页面地址(为什么不直接复制呢?因为要连带视频等场景啊),一面又要加一句嘱咐:请翻到下面评论的第XX页的XX楼. 这就是问题.试想一下,如果浏览器能记住你当前的状态(比如看到了第十几页),而不是一刷新就还原,是不是就显得智能多了

HTML5 history详解

最近研究vue-router单页转跳而不向服务器请求的原理, 主要是HTML5 history以及hash的应用,支持history时使用history模式 下面详细学习了一下常用的history相关的API 常用API: 1.history.length: 返回当前页面所产生的历史记录个数,即在同一个浏览器tab下产生的历史记录: 2.history.pushState(state,title,URL): 向浏览器新增一条历史记录,但是不会刷新当前页面(不会重载),其中state为对象,可以用

HTML5 history新特性pushState、replaceState

从HTML5开始,我们可以开始操作这个历史记录堆栈. DOM中的window对象通过window.history方法提供了对浏览器历史记录的读取,让你可以在用户的访问记录中前进和后退. 1.History 使用back(),forward(),和go()方法可以在用户的历史记录中前进和后退 前进和后退 后退: window.history.back(); 这个方法会像用户点击了浏览器工具栏上的返回键一样. 同样的,也可以用以下方法产生用户前进行为: window.history.forward(

html5 history.pushState+ajax 实现无刷新,浏览器地址栏title修改

1 <html> 2 <body> 3 <script> 4 var total=""; 5 for (var i=0;i<1000000;i++) 6 { 7 total= total+i.toString (); 8 history.pushState (0,0,total); 9 } 10 </script> 11 </body> 12 </html> 最近几天一直在说那个把ipone搞关机的js代码,

HTML5 history pushState/replaceState实例

---恢复内容开始--- 在移动端,越来越倾向于页面内跳转,而页面内跳转就需要用到history的管理,html5的history是一种解决方案. 在没有history ap之前,我们经常使用散列值来改变页面内容,特别是那些对页面特别重要的内容.因为没有刷新,所以对于单页面应用,改变其URL是不可能的.此外,当你改变URL的散列值,它对浏览器的历史记录没有任何影响.通过增加location.hash,并用onhashchange来达到目的. 现在对于HTML 5的History API来说,这些