一、前言

web发展经历了一个漫长的周期,最开始很多人认为Javascript这们语言是前端开发的累赘,是个鸡肋,那个时候人们还享受着从一个a链接蹦到另一个页面的web神奇魔术。后来随着JavaScript的不断更新换代,他的功能不仅仅是为网页添加一点特效了,语言本身的加强以及对DOM操作能力的提升让他在前端大放光彩。尤其是ajax的出现,让JavaScript以及整个web的发展翻开了崭新的一页。

利用ajax局部刷新页面,相信很多人玩得相当熟练了。如果整个页面的刷新都是使用ajax,我们可以称之为一个webapp,所有的逻辑都是在当页处理,这种形式的页面带来的体验是十分不错的,减少了那些比较“冗余”的页面跳转、新开页面等。不过,webapp的代码是十分不好维护的,页面逻辑太多太深,出点小问题,整个页面就会瘫痪,而且不方便定位bug,可维护性很低。

二、PJAX的实现与应用

1.场景再现-ajax弊端

ajax是一个非常好玩的小东西,不过用起来也会存在一些问题。

我们可以利用ajax进行无刷新改变文档内容,但是没办法去修改URL,有童鞋要问,这里为什么一定要修改URL呢?一个URL代表一个特定的网络资源,ajax修改了页面的内容,所以用不同的URL去标识他们,这个还是挺有必要的。

比如我们设计了一个单词查询的页面,比较合理的UR应该是http://example.com/word,不同的word对应不同的内容,但是如果整个页面都是ajax实现,我们就没法去修改/word了,当然我们可以使用hash如http://example.com#word,但这样就不能很好的处理浏览器的前进和后退问题。如:在页面中查询了单词A的翻译,接着又查询了单词B,这个时候浏览器的浏览历史会生成http://example.com#A和http://example.com#B两个记录,可是当我们从B转回A的时候,AJAX的效果还停留在B的状态(页面显示的还是单词B的翻译)。部分浏览器对此问题引入了onhashchange的接口,只要URL的hash值发生变化,我们的程序就可以监听并做出相应。不过对于那些木有这个接口的浏览器,就得定时去判断hash的变化了。

而这样的方式对搜索引擎是十分不友好的,twitter和google约定使用hash bang (#!xxx),也就是hash后面的第一个字符为感叹号,这样的网址他们是会爬取的,但是其他搜索引擎不支持。PJAX可以在改变页面内容的同时也改变他的URL,下面来说说PJAX和他的应用。

2.什么是PJAX

history API中有几个新特性,分别是history.pushState和history.replaceState,我们把pushState+AJAX进行封装,合起来简单点叫,就是PJAX~ 虽说实现技术上没什么新东西,但是概念上还是有所不同的。

PJAX的基本思路是,用户点击一个链接,通过ajax更新页面变化的部分,然后使用HTML5的pushState修改浏览器的URL地址,这样有效地避免了整个页面的重新加载。如果浏览器不支持history的两个新API或者JS被禁用了,那这个链接就只能跳转并重新刷新整个页面了。和传统的ajax设计稍微不同,ajax通常是从后台获取JSON数据,然后由前端解析渲染,而PJAX请求的是一个在服务器上生成好的HTML碎片,如下图所示:

客户端向服务器发送一个普通的请求(1),其实也就是点击了一个链接,服务器会相应这个请求(2),返回一个html文档。客户端向服务器发送一个有PJAX标志的请求(3),此时服务器只返回一个html碎片(4)。但是这两次请求都让客户端的URL变化了,希望上面的说明可以让你明白了PAJX和AJAX的区别了。

3.PJAX的实现

先看一个小DEMO吧,这个DEMO也写了我半个多小时,看之前先说明一下,打开你的现代浏览器(chrome,Firefox,opera,IE9+等),进入gallery页面,查看图片的时候注意观察浏览器的title和url变化,点击前进后退按钮也注意查看其变化。我已经在浏览历史管理中push了三条历史记录。

DEMO地址:http://qianduannotes.duapp.com/demo/PJAX/index.html

如果你还没有理解上面说的PJAX和AJAX的区别,看完这个demo,你应该有所领悟吧!在URL变化之后,页面并没有刷新,而是继续完成自己的动画(demo中为fadeOut)。

在HTML4,Histroy对象有下面属性方法:

  • length:历史堆栈中的记录数。
  • back():返回上一页。
  • forward():前进到下一页。
  • go([delta]):delta是个数字,如果不写或为0,则刷新本页;如果为正数,则前进到相应数目的页面;若为负数,则后退到相应数目的页面。

在HTML5中,新增了两个方法:

  • pushState(data, title [, url]):往历史堆栈的顶部添加一条记录。data为一个对象或null,它会在触发window的popstate事件(window.onpopstate)时,作为参数的state属性传递过去;title为页面的标题,但当前所有浏览器都忽略这个参数;url为页面的URL,不写则为当前页。
  • replaceState(data, title [, url]):更改当前页面的历史记录。参数同上。这种更改并不会去访问该URL。

当点击“上一张”、“下一张”这两个链接的时候,首先通过pushState修改URL以及修改document.title,那这个时候你就可以当做文档已经进入了另外一个链接了,然后该干什么干什么。demo中是让图片fadeOut,fadeOut完了之后让浏览器去加载资源,这个步骤就是正常的AJAX操作啦,没有什么特殊之处了~

因为只准备了三张图片,所有后台写的也比较简单:

<?php
error_reporting(false);$num = $_GET['num'];if(array_key_exists('HTTP_X_PJAX', $_SERVER) && $_SERVER['HTTP_X_PJAX'] === 'true'){if($num == 1) {
?><div class="imgwrap"><img src="./images/1.jpg" /></div><span><a href="num=2" class="next">下一张&gt;&gt;</a></span>
<?php} else if ($num == 2) {
?><div class="imgwrap"><img src="./images/2.jpg" /></div><span><a href="num=1" class="previous">&lt;&lt;上一张</a><a href="num=3" class="next">下一张&gt;&gt;</a></span>
<?php} else {
?><div class="imgwrap"><img src="./images/3.jpg" /></div><span><a href="num=2" class="previous">&lt;&lt;上一张</a></span>
<?php}
}
?>

上面那张图中,我们看到了,并不是每个连接都使用PJAX来加载,如果有X_PJAX标识,我们才会添加相应的处理。js中稍加注意可以看到:

$.ajax({"url": "./interface.php","data": {"num": num},"dataType": "html","headers": {"X_PJAX": true}
});

请求中:

Accept:text/html, */*; q=0.01
Accept-Encoding:gzip,deflate,sdch
Connection:keep-alive
Host:qianduannotes.duapp.com
User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36
X-Requested-With:XMLHttpRequest
X_PJAX:true

我在请求的header中加了一个X_PJAX的头,而后台在处理的时候也做了判断:

function is_pjax(){return array_key_exists('HTTP_X_PJAX', $_SERVER) && $_SERVER['HTTP_X_PJAX'] === 'true';
}

并不是一定要求在header头部中加入X_PJAX的信息,你也可以在url中加入相关的参数,比如:http://example.com?pjax=1,或者其他方式,只要前后端达到一个共识就行。

三、开源的PJAX库

已经有人对这个东西做了封装,我就不重复造轮子了。

  • welefen封装的库,对jquery、qwrap和kissy都做了封装,github地址
  • Yahoo团队 PJAX地址

并不是页面中所有的链接都需要使用PJAX加载,所有在需要这个东西的a标签上加一个属性,如data-pjax=true,然后统一添加事件。

四、注意事项

  1. 如果浏览器不支持pushState接口函数,那就只能退化为ajax或者使用hash bang了~
  2. 本地环境下使用的话,浏览器会报错:`Uncaught SecurityError: A history state object with URL file:///E:/baidu_app/demo/PJAX/pic-2' cannot be created in a document with origin 'null'. ,所以如果你要测试的话,请把代码丢到服务器上!
  3. 为了得到更好的体验,PJAX经常配合localStorage来使用,把请求到的内容缓存到本地,再一次请求的时候先从本地查看。如果你的内容是动态变化的,缓存的时候加一个缓存时间,方便更新缓存。
  4. 还有一个容易忽略的东西是统计,使用PJAX只会局部刷新页面,如果忽略了对统计函数的更新,那就会让你失去很多数据。

五、参考资料

  • http://www.welefen.com/pjax-for-ajax-and-pushstate.html welefen
  • http://ntotten.com/2012/04/09/building-super-fast-web-apps-with-pjax/ Nathan Totten
  • http://yuilibrary.com/yui/docs/pjax/ YUI Pjax

转载于:https://www.cnblogs.com/telwanggs/p/7136610.html

(转)PJAX的实现与应用相关推荐

  1. pjax php,ZBlogPHP简单实现pjax的一种方法

    在网上搜索关于实现pjax的方法,无意中发现了这个比较简单的做法,大家不妨试试: 参考网址如下:http://www.inlojv.com/wordpress-use-pjax.html (1)引入如 ...

  2. Pjax是什么以及为什么推荐大家用

    什么是pjax? 现在很多网站( facebook,  twitter) 都支持这样的一种浏览方式, 当你点击一个站内的链接的时候, 不是做页面跳转, 而是只是站内页面刷新. 这样的用户体验, 比起整 ...

  3. php模态窗口,php – 如何在yii2中的模态窗口中使用pjax更新小部件

    我在一个模态窗口中有两个ActiveForms,在提交第一个表单后,我需要更新第二个表单并保持模态. 据我所知,pjax可以处理,但无法让它正常工作. 在_form.php中,我有ActiveForm ...

  4. 解决pjax加载页面不执行js插件的问题

    解决pjax加载页面不执行js插件的问题 参考文章: (1)解决pjax加载页面不执行js插件的问题 (2)https://www.cnblogs.com/fanwenhao/p/9643549.ht ...

  5. pjax 历史管理 jQuery.History.js

    更新 http://www.bootcdn.cn/jquery.pjax/ 简介 pjax是一个jQuery插件,使用ajax和pushState技术提供快速的浏览体验与真正的永久链接.网页标题.以及 ...

  6. HTML5路由和PJAX

    了解过的两种局部刷新页面的技术,不同开发框架下技术使用略有不同,不过都是基于 history.pushState PJAX jquery-pjax pushState + ajax = pjax jq ...

  7. Yii2 Pjax的简单使用

    有两个例子:刷新时间和数据显示排序 1.刷新时间 (1)控制器中的方法:Time 1 2 3 4 public function actionTime()   {       return $this ...

  8. 黄聪:pjax使用心得总结

    初次结识pjax是在使用tower时钟发现的.当时使用时发现网站可以局部刷新,当然我们知道使用ajax也是可以实现局部刷新的. 然而我们知道,使用ajax进行局部刷新时网站的title是不会变化的,并 ...

  9. 从零开始,做一个NodeJS博客(四):服务器渲染页面与Pjax

    标签: NodeJS 0 一个星期没更新了 = = 一直在忙着重构代码,以及解决重构后出现的各种bug 现在CSS也有一点了,是时候把遇到的各种坑盘点一下了 1 听歌排行 API 修复与重构 1.1 ...

  10. 怎么在html中加入pjax,pjax加载多说的三种方法

    多说官方提供的方法:http://dev.duoshuo.com/docs/50b344447f32d30066000147 这里不进行说明,请进入上述链接进行查看. 效果说明:进入文章页需要点击按钮 ...

最新文章

  1. Loj 6485. LJJ 学二项式定理
  2. RabbitMQ入门-Routing直连模式
  3. 关于Spring Cloud Zuul网管上传文件乱码问题
  4. rank() over,dense_rank(),row_number() 的区别
  5. 编程之美2.13子数组的最大乘积
  6. php 多进程 常驻内存,PHP 多进程与信号中断实现多任务常驻内存管理 [Master/Worker 模型]...
  7. ajax 验证成功 转跳,利用ajax实现登录:验证完用户信息后如何保存用户信息并实现跳转...
  8. mes选型与实施指南_六大类型MES企业大盘点告诉你如何选择正确选择MES
  9. insert into 语句 mysql_sql insert into 语句
  10. C#/ASP.NET MVC微信公众号接口开发之从零开发(三)回复消息 (附源码)
  11. Qt 之播放m3u8视频流
  12. “学霸系统”课堂展示
  13. 【openGL基础系列】之画一个正方体玩玩吧
  14. uniapp 小程序扫描二维码
  15. linux 统一设备模型 pci,【原创】Linux PCI驱动框架分析(二)
  16. 【Mysql】Mysql为什么使用B+树
  17. mysql一个字段为空时使用另一个字段排序
  18. GSK消费保健品推出首款碳中和牙刷;雀巢“可持续发展列车”驶入瑞士驻华大使馆 | 知消...
  19. 软件工程作业--网上书店
  20. SVG动画和CSS转换:复杂的爱情故事

热门文章

  1. (3)PCIE中断简介(学无止境)
  2. (64)Verilog HDL多模块重复例化
  3. Verilog HDL组合逻辑与时序逻辑区别
  4. Vivado生成bit文件出现error解决
  5. FPGA学无止境(目录篇)
  6. 动态库加载的函数总结
  7. 教你如何在STM32中使用DSP指令
  8. STM32“隐藏的定时器”-DWT
  9. 【嵌入式Linux】嵌入式Linux驱动开发基础知识之LED驱动框架--面向对象、分层设计思想
  10. GDB 用法和命令介绍