使用 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; ...
随机推荐
- [开发工具]_[VS2010]_[vs2010的一个bug-使用stringstream时出现]
1. 注冊Microsfot之后想提交bug, 发现有这个提示, 所以提交不了bug, 有能提交的提交下吧. You are not authorized to submit the feedback ...
- spring中ApplicationContextAware接口使用理解
一.这个接口有什么用?当一个类实现了这个接口(ApplicationContextAware)之后,这个类就可以方便获得ApplicationContext中的所有bean.换句话说,就是这个类可以直 ...
- mysql必知必会(四、检索数据,五、排序检索数据,六、过滤数据,七、数据过滤)
四.select语句 1.检索单个列 select prod_name from products; 2.检索多个列 select prod_name, prod_price from product ...
- Android6.0执行时权限解析,RxPermissions的使用,自己封装一套权限框架
Android6.0执行时权限解析,RxPermissions的使用.自己封装一套权限框架 在Android6.0中,新添加了一个执行时的权限,我相信非常多人都已经知道了.预计也知道怎么用了,这篇博客 ...
- Web.config中加了system.diagnostics节点后就不能访问了
Web.config中加了system.diagnostics节点后就不能访问了,怎么回事? [解决方法] 不要把system.diagnostics节点作为web.config的第一个节点.
- mac利用Synergy操作多台电脑
话说,我现在桌子上有3台电脑,但是我只有一个鼠标和键盘,我该怎么玩呢,就像win一样,可以外接一个显示器,鼠标到达了显示器边缘自动翻越到另一个显示器上,这个没问题,win已经实现了. 我今天推荐一款牛 ...
- QQ2010如何开启透明效果皮肤
QQ2010可在WIN7下实现皮肤透明效果. 腾讯已于近日发布了QQ2010的BETA版本,经笔者试验,可在WIN7下实现皮肤透明化效果. 设置如下: 1.先打开QQ皮肤控制面板,如下: 2.然后任选 ...
- HttpContext.Current.Cache 和 HttpRuntime.Cache
HttpRuntime.Cache:用于winfrom 和 web HttpContext.Current.Cache 用于web .NET中Cache有两种调用方式:HttpContext.Curr ...
- Wireshark基本介绍和TCP三次握手
转自:http://www.cnblogs.com/TankXiao/archive/2012/10/10/2711777.html 之前写过一篇博客:用 Fiddler 来调试HTTP,HTTPS. ...
- 算法笔记_196:历届试题 剪格子(Java)
目录 1 问题描述 2 解决方案 1 问题描述 问题描述 如下图所示,3 x 3 的格子中填写了一些整数. +--*--+--+|10* 1|52|+--****--+|20|30* 1|**** ...