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)
- // @state状态对象:记录历史记录点的额外对象,可以为空
- // @title页面标题:目前所有浏览器都不支持
- // @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。
注意点:
- javascript脚本执行window.history.pushState和window.history.replaceState不会触发onpopstate事件。
- 谷歌浏览器和火狐浏览器在页面第一次打开的反应是不同的,谷歌浏览器奇怪的是回触发onpopstate事件,而火狐浏览器则不会。
实例Demo
页面css如下:
body {
overflow-x: hidden;
}
ul {
padding:;
margin:;
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:;
}
.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:;
}
.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改变了,而且可以通过无刷新的请求回退状态,真的是无限级的提高了用户友好性。
浏览器支持情况

HTML5 history的更多相关文章
- HTML5 History API 实现无刷新跳转
在HTML5中, 1. 新增了通过JS在浏览器历史记录中添加项目的功能. 2. 在不刷新页面的前提下显示改变浏览器地址栏中的URL. 3. 添加了当用户单击浏览器的后退按钮时触发的事件. 通过以上三 ...
- HTML5 History API实现无刷新跳转
在HTML5中, 新增了通过JS在浏览器历史记录中添加项目的功能. 在不刷新页面的前提下显示改变浏览器地址栏中的URL. 添加了当用户单击浏览器的后退按钮时触发的事件. 通过以上三点,可以实现在不刷新 ...
- html5 history api
1.html5 history api适用场景,个人理解最大的用处是配合ajax使用,使ajax拥有回退.前进的用户体验. 2.代码(dive into html5中的一个小例子) 1)fer.htm ...
- HTML5 history API实践
一.history API知识点总结 在HTML4中,我们已经可以使用window.history对象来控制历史记录的跳转,可以使用的方法包括: history.forward();//在历史记录中前 ...
- Ajax异步刷新地址栏url改变(利用Html5 history.pushState实现)
早些时候在博客园参阅了不少资料,然后决定入驻博客园分享自己的开发心得,最近准备转方向筹备着辞职交接工作,所以有点忙碌,搁置了一个月才匆匆写下这么一篇随笔,希望能给大家带来一点帮助吧,资料和学识有限,如 ...
- ajax与HTML5 history pushState/replaceState实例
一.本文就是个实例展示 三点: 我就TM想找个例子,知道如何个使用,使用语法什么的滚粗 跟搜索引擎搞基 自己备忘 精力总是有限的,昨天一冲动,在上海浦东外环之外订了个90米的房子,要借钱筹首付.贷款和 ...
- HTML5 History对象,Javascript修改地址栏而不刷新页面(二)
一.实例说明: $('#btnOne').click(function () { var stateObject = { id: 1 }; var title = "本地首页"; ...
- 转: html5 history api详解~很好的文章
从Ajax翻页的问题说起 请想象你正在看一个视频下面的评论,在翻到十几页的时候,你发现一个写得稍长,但非常有趣的评论.正当你想要停下滚轮细看的时候,手残按到了F5.然后,页面刷新了,评论又回到了第一页 ...
- HTML5 History API & URL 重定向
HTML5 History API & URL 重定向 disabled server url redirect https://developer.mozilla.org/en-US/doc ...
- html5 - history 历史管理
参考文章: w3c : http://www.w3.org/html/ig/zh/wiki/HTML5/history 张鑫旭 : http://www.zhangxinxu.com/wo ...
随机推荐
- js前端分页
转载:http://www.cnblogs.com/lyzg/p/5791011.html http://www.cnblogs.com/m-m-g-y0416/p/5601903.html
- JavaScript变量的作用域和函数的作用域的区别
变量作用域和函数作用域都涉及到变量值的变化,本文旨在让大家明白他们之间的区别 变量的作用域: 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接 ...
- vim 插件管理
1 进入自己的vim mkdir ./bundle/vundle 2 在vimrc同级中执行 git clone https://github.com/gmarik/vundle.git ./bund ...
- 77 swapon-激活Linux系统中交换空间
Linux swapon命令用于激活Linux系统中交换空间,Linux系统的内存管理必须使用交换区来建立虚拟内存. 语法 /sbin/swapon -a [-v] /sbin/swapon [-v] ...
- killall 根据名称终止进程
根据名称终止进程 killall [option] name-list killall 将信号发送到一个或多个进程用来终止它.除超级用户外,只有进程的所有者才可以对进程执行killall,超级用户可以 ...
- 【心得】怪异的JS的Date函数
我们知道new Date('2013/1/1')是2013年1月1日, 那么new Date('2013/1/366')会报无效日期格式吗?答案是,这是一个有效的日期,但是他是表示2014年1月1日. ...
- 基于tiny4412原生uboot修改制作SD启动并烧写到emmc
最近入手tiny4412的标准板,底板SDK型号为1506.但是因为友善之臂提供的superboot不能进入boot菜单,此时我就不能通过tftp下载内核和通过nfs挂载根文件系统,于是想自己做个ub ...
- HTML5基础知识(2)--标题标签的使用
1.HTML文档中包含各种级别的标题,各种级别的标题由<h1>到<h6>元素来定义,<h1>至<h6>标题标记中的字母h是英文headline的简称.其 ...
- java学习笔记--java中的基本数组[5]
java基础很重要, 今天呆家看java视频,顺便总结前几周看的java书籍,做一下简单的总结:1:数组的声明,2:数组的赋值: 3:数组的方法: 声明一个数组主要有两种方式: //类型 []数组名字 ...
- js-格式化数字保留两位小数-带千分符
很多时候发现有时候js会提示自带函数不能使用,所以自己找了很多资料实现了个 html <input type="text" class="input_text in ...