Pjax(pushState and Ajax)

一.Pjax是啥?

Pjax = history.pushState + Ajax
     = history.pushState + Async JS + XML(xhr?)

BOM对象history被增强了一波,主要是对历史栈的操作,以前只有replace, go之类的,都会跳转并刷新整个页面,现在有了pushState, replaceState等等单纯操作历史栈的方法,只是单纯修改历史栈里的内容,没有副作用(页面不会跳转刷新)

关于history对象的更多信息请查看MDN History

二.Pjax有什么用?

1.最初的单页面应用(SPA)

页面刷新不仅浪费资源(很多同级页面上大部分内容都是相同的,没必要重新加载这些重复内容),还影响用户体验(loadingloadingloading…)。局部刷新能够避免loading影响用户体验,从Ajax概念一出来就有人开始这么做了,把整站做成单页面应用(Single Page App,简称SPA),Ajax请求JSON,再局部刷新呈现数据,最初的SPA存在很多缺点:

  • 最大的问题:页面内容与URL不对应

    这是致命的缺点,用户看到的内容与地址栏URL不对应,意味着内容无法分享传播(分享传播太重要了),浏览器前进/后退按钮也无法按照用户预期工作

  • 其次:破坏SEO

    纯Ajax实现的SPA对SEO有极大的消极影响,由于页面上很多内容都是Ajax请求之后js控制呈现的,蜘蛛看不到这些内容,也就根本不会被索引/收录

2.pretty AJAX URL

为了解决SEO问题,Google提出了一种很丑(虽然名字叫pretty AJAX URL。。)的方法:#!

据说Twitter用过一个月,后来用户反馈说太丑了,再后来就不用了。这种很丑的url确实能解决上述的第2个问题,但是需要搜索引擎配合,Google认可这种方式,Google的蜘蛛会把mydomain.com/index.html#!article1mydomain.com/index.html#!article2当作两个不同的页面对待,服务给这种特殊URL的请求返回对应的页面即可,SEO问题没了。

但第一个问题还在,页面内容与URL仍然不对应,于是有了下面要说的Pjax

3.Pjax

W3C提出了新的API,增强了history对历史栈的控制能力,能够直接修改地址栏URL,直到这时页面内容与URL才终于能够对应了

每次局部刷新成功之后都调用history.pushState同步更新地址栏的URL(维护历史栈),这些URL都对应可以直接访问的页面,每个局部刷新动作都是由a标签触发的,js拦截默认跳转,再Ajax请求数据呈现数据,用户看到的是局部刷新和流畅的体验,蜘蛛看到的是普通的a标签页面跳转,页面展示的内容始终与直接访问URL得到的内容一致,致命缺点也不存在了

如果各个浏览器支持性良好的话,Pjax能够完美支持单页面应用,如果浏览器不支持新API就把它当蜘蛛好了(目前好像没有好用的兼容方案,jq插件也无能为力),至于css/js冲突、内存泄露等等都是SPA本身的问题,成熟的SPA方案应该可以避免这些问题

三.Pjax怎么用?

核心是2个方法和1个事件:

  • history.pushState(state, title, url);

  • history.replaceState(state, title, url);

  • popstate

其中state参数是自定义obj,可以通过history.state拿到,title参数没什么用,浏览器都不认pushreplace的区别是前者把指定url入栈,后者换掉栈顶元素。浏览器的前进/后退会触发popstate,可以在里面根据history.state数据作出相应处理

前辈有一个比较简洁的DEMO:ajax与HTML5 history pushState/replaceState实例

此外,也有相应的开源库可以使用:

四.为什么要用Pjax?

在不影响SEO的前提下,局部刷新 + 本地缓存能够带来前所未有的快速体验,这是Pjax的绝对优势

Pjax适用于非纯移动端的单页面应用,能够实现流畅的用户体验,而且封装好的Pjax组件支持一些额外的功能,比如缓存、本地存储、动画等等,使用起来也很方便

移动页面一般不存在频繁地大篇幅页面内容更新,而且移动页面很少需要考虑SEO,直接用Ajax即可

五.Pjax案例

参考资料

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*

code