使用 HTML5 History 新特性增强 Ajax 的体验(转)
一. 场景再现
如大家熟知,Ajax 可以实现页面的无刷新操作,但会造成两个与普通页面操作(有刷新地改变页面)有着明显差别的问题—— URL 没有修改以及无法使用前进、后退按钮。例如常见的 Ajax 分页,在第一页点击第二页的链接,Ajax 分页完成后浏览器地址栏上显示的 URL 依然是第一页的 URL,使用后退按钮也无法回到第一页。url 的改变代表一个标识,在传统的网页体验中,内容的变更伴随 url 的改变,url 的改变、前进和后退按钮三者之间更加形成一种独特的导航体验,而 Ajax 破坏了这种体验难免会对用户造成不便。
当然,很早之前,机智的前端工程师们已经想好了解决办法,最为常见的,就是使用 hash ——在 URL 结尾添加形如"#xxx" 的标识,然后用 onhashchange 等方式监听 hash 值变化作出相应处理。
很麻烦?是的,因此,HTML5 History 中新增了几个可以优雅地解决这些问题的特性!
二. HTML5 History 的新特性
History 对象从 HTML4 开始引入,HTML5 中增加了 pushState, replaceState 两个方法,和 popstate 事件。下面作一些简单的介绍。
1. pushState()方法
pushState() 的作用是往历史记录的堆栈中压入一条记录,该方法有三个参数:
state object —— 一个对象,用于保存状态信息,当 popstate 事件被触发时,popstate 事件对象的 state 属性会包含相应的 state object 的拷贝。state object 的容量很小(Firefox 中强制为 640k),如果需要储存较大的数据,建议使用 localStorage 或 sessionStorage。
title —— 即被压入的历史记录的页面的标题,该属性暂时被所有浏览器忽略,实际开发时可以填空字符或一个简短的标题。
url —— 新的历史记录的地址,可以是相对路径或绝对路径,若为相对路径则以当前 url 为基址。
2. replaceState()方法
replaceState() 方法与 pushState() 方法类似,参数与 pushState() 也相同,但 replaceState() 方法会修改当前的历史记录而并非创建新的记录,因此在需要更新当前历史记录的 state object 或 URL 时,使用该方法会更加合适。
3. popstate 事件
popstate 事件会在激活的历史记录发生变化(如前进、后退、调用 pushState 或 replaceState 方法)时触发在 window 对象上。如上面所描述,如果被激活的历史记录由 pushState 创建或是被 replaceState 修改,则 popstate 事件的状态属性将包含相应的 state object 的拷贝,开发者可以在 popstate 的回调中调用这些之前保存在 state object 中的信息。
值得注意的是,Chrome 会在打开页面(包括第一次打开页面)以及页面刷新时产生 popstate 事件而 Firefox 则不会,这会为开发带来一些麻烦,但下面会给出解决方案。
4. 浏览器兼容
| 特性 | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
|---|---|---|---|---|---|
| pushState, replaceState | 5 | 4.0 (2.0) | 10 | 11.50 | 5.0 |
| history.state | 18 | 4.0 (2.0) | 10 | 11.50 | 6.0 |
三. 使用 History 的新特性增强 Ajax 体验
这里说的增强体验,实质就是要解决文章开头提到的两个问题 —— Ajax 翻页时不会修改 URL 以及前进、后退功能无效。
看了上面的方法,相信大家已经能想到基本的解决思路,无非就是在 Ajax 需求产生时 pushState 一条记录到历史记录中,然后在 popstate 的回调函数中作出相应的处理。当然,要想实际获得比较好的体验,要做的内容还是比较复杂的。下面以 Ajax 分页为例,提供一个完整思路:
- 每次使用 Ajax 获取新页面后,使用 pushState() 把新页面的 url 压入历史记录栈顶。
- 监听 popstate 事件,当用户前进或后退时在回调中根据前进或后退后的 URL 重新使用 Ajax 获取页面内容,实现 Ajax 前进与后退。
- Chrome 在打开页面以及刷新页面后会产生 popstate 事件,导致多余的 Ajax 请求,因此需要 popstate 中利用 url 作为判断用户是否在点击前进或后退功能,抑或是打开、刷新页面,若为前进或后退才触发 Ajax 获取相应内容。
基本代码
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
// 定义 Ajax 获取分页方法,这里不列出具体内容function turnPage(url){ // ...}// 定义 popstate 的回调if( history.pushState ){ // 判断浏览器是否支持 pushState // currentState 用于记录 popstate 产生前的页面 url,页面加载时初始化 currentState 为当前链接 var currentState = window.location.href; window.addEventListener('popstate', function(event){ // _currentUrl 用于记录 popstate 产生时的页面 url var _currentUrl = window.location.href; /* 判断 currentState 和 _currentUrl 是否相同, * 若相同则表明这个 popstate 产生前后页面 url 没有变化, * 即页面是第一次加载页面或者被刷新,无需触发新的 Ajax 请求, * 若不同则表明 url 已改变,这是触发 Ajax 获取内容 */ if( currentState != _currentUrl ){ console.log('获取新分页'); turnPage(_currentUrl); // 根据当前 url 重新获取分页内容 currentState = _currentUrl; // 更新 currentState } });}// 绑定点击分页产生 Ajax 请求// 点击分页链接,获取 url 为 currentLink,产生一次 Ajax 请求turnPage(currentLink);// 调用 pushState() 压入新记录if( history.pushState ){ // 判断浏览器是否支持 pushState // 往历史记录中压入新记录,浏览器的地址栏上的 url 同时会被修改为新 url history.pushState(null, document.title, currentLink); currentState = window.location.href; // 分页时更新 currentState 为当前 url} |
本站已经根据上面的思路进行了 Ajax 分页的增强,具体的情况如下:
打开页面,url 显示为首页的 url

点击第二页链接,触发 Ajax 分页,在 Ajax 中调用 pushState() ,可以看到,url 已经被修改为第二页的 url

点击后退按钮,url 地址变为第一页,再在 popstate 的回调中触发 Ajax 获取第一页的内容。
这样,就做到了既吸收了局部刷新页面的好处同时保留传统的 url 导航体验。而对于不支持 pushState 的浏览器,可以使用渐进增强设计忽略这些浏览器,毕竟这是一个增强体验的功能;当然如果必须照顾那些浏览器,也可以采用 hash 的方案代替。
四. 现有的解决方案
如果需要直接的解决方案,可以参考这个封装好并且实现了跨浏览器兼容的库 —— History.js
本文由 Kayo Lee 发表,本文链接:http://kayosite.com/html5-history-improve-ajax.html
使用 HTML5 History 新特性增强 Ajax 的体验(转)的更多相关文章
- HTML5 history新特性pushState、replaceState
DOM中的window对象通过window.history方法提供了对浏览器历史记录的读取,让你可以在用户的访问记录中前进和后退. 从HTML5开始,我们可以开始操作这个历史记录堆栈. 1.Histo ...
- HTML5 history新特性pushState、replaceState,popstate
http://blog.csdn.net/tianyitianyi1/article/details/7426606 https://developer.mozilla.org/zh-CN/docs/ ...
- 浅谈HTML5的新特性
2014年10月29日,W3C宣布,经过接近8年的艰苦努力,HTML5标准规范终于制定完成. HTML5将会取代1999年制定的HTML 4.01.XHTML 1.0标准,使网络标准达到符合当代的网络 ...
- Atitti html5 h5 新特性attilax总结
Atitti html5 h5 新特性attilax总结 Attilax觉得不错的新特性 3.语义Header和Footer (The Semantic Header and Footer) 8.占位 ...
- Atitit html5.1 新特性attilax总结
Atitit html5.1 新特性attilax总结 9. 嵌入 header 和 footer1 7. 校验表单1 6. 浏览器的上下文菜单2 1. 响应式图像2 Attilax觉得还不错的心特性 ...
- HTML5的新特性:范围样式,又叫做<style scoped>
Chromium 最近实现了一个HTML5的新特性:范围样式,又叫做<style scoped> .开发者可以通过为根元素设定一个添加了scoped属性的style标签,来限制样式只作用于 ...
- C# 9 新特性 —— 增强的 foreach
C# 9 新特性 -- 增强的 foreach Intro 在 C# 9 中增强了 foreach 的使用,使得一切对象都有 foreach 的可能 我们来看一段代码,这里我们试图遍历一个 int 类 ...
- C# 9 新特性 —— 增强的模式匹配
C# 9 新特性 -- 增强的模式匹配 Intro C# 9 中进一步增强了模式匹配的用法,使得模式匹配更为强大,我们一起来了解一下吧 Sample C# 9 中增强了模式匹配的用法,增加了 and/ ...
- jdk1.5出现的新特性---->增强for循环
import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; ...
随机推荐
- 卡方检验(Chi-square test/Chi-Square Goodness-of-Fit Test)
什么是卡方检验 卡方检验是一种用途很广的计数资料的假设检验方法.它属于非参数检验的范畴,主要是比较两个及两个以上样本率( 构成比)以及两个分类变量的关联性分析.其根本思想就是在于比较理论频数和实际频数 ...
- Jquery Mobile实例--利用优酷JSON接口读取视频数据
本文将介绍,如何利用JqueryMobile调用优酷API JSON接口显示视频数据. (1)注册用户接口. 首页,到 http://open.youku.com 注册一个账户,并通过验证.然后找到A ...
- 数学图形之莫比乌斯带(mobius)
莫比乌斯带,又被译作:莫比斯环,梅比斯環或麦比乌斯带.是一种拓扑学结构,它只有一个面(表面),和一个边界.即它的正反两面在同一个曲面上,左右两个边在同一条曲线上.看它的名字很洋气,听它的特征很玄乎,实 ...
- Lichee (五) sysconfig1.fex 配置系统
sysconfig配置系统,作为一个通用的软件平台,还希望通过它,可以适应用户不同的方案.通过给出一个对应的配置,用户的方案就可以自动运行,而不需要修改系统里面的代码,或者重新给出参数. 配置脚本的本 ...
- std::vector利用swap()函数进行内存的释放【转】
首先,vector与deque不同,其内存占用空间只会增长,不会减小.比如你首先分配了10,000个字节,然后erase掉后面9,999个,则虽然有效元素只有一个,但是内存占用仍为10,000个.所有 ...
- Faster\Slower 快慢指针的应用
leetcode很多题目都是利用快慢指针来解决题目,下面具体讲解下快慢指针. 概念: 快指针在每一步走的步长要比慢指针一步走的步长要多.快指针通常的步速是慢指针的2倍.在循环中的指针移动通常为:fas ...
- Reverse Nodes in k-Group leetcode java
题目: Given a linked list, reverse the nodes of a linked list k at a time and return its modified list ...
- 【架构】Kubernetes和Spring Cloud哪个部署微服务更好?
Spring Cloud 和Kubernetes都自称自己是部署和运行微服务的最好环境,但是它们在本质上和解决不同问题上是有很大差异的.在本文中,我们将看到每个平台如何帮助交付基于微服务的架构(MSA ...
- .NET MVC自定义错误处理页面的方法
在ASP.NET MVC中,我们可以使用HandleErrorAttribute特性来具体指定如何处理Action抛出的异常.只要某个Action设置了HandleErrorAttribute特性,那 ...
- 查看sedna创建的数据库和集合,文档之类
在sedna的安装文件夹下.看一下cfg文件夹: <pre name="code" class="plain">[xuzhina@localhost ...