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

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

用法

  1. 引入jquery和jquery.pjax.js
  2. 注册事件
    /**
    * 方式一 按钮父节点监听事件
    *
    * @param selector 触发点击事件的按钮
    * @param container 展示刷新内容的容器,也就是会被替换的部分
    * @param options 参数
    */
    $(document).pjax(selector, [container], options);
    // 方式二 直接对按钮监听,可以不用指定容器,使用按钮的data-pjax属性值查找容器
    $("a[data-pjax]").pjax();
    // 方式三 常规的点击事件监听方式
    $(document).on('click', 'a', $.pjax.click);
    $(document).on('click', 'a', function(event) {
    var container = $(this).closest('[data-pjax-container]');
    $.pjax.click(event, container);
    });
    // 下列是源码中介绍的其他用法,由于本人暂时没有那些需求暂时没深究,有兴趣的各位自己试试看哈
    // 表单提交
    $(document).on('submit', 'form', function(event) {
    var container = $(this).closest('[data-pjax-container]');
    $.pjax.submit(event, container);
    });
    // 加载内容到指定容器
    $.pjax({ url: this.href, container: '#main' });
    // 重新当前页面容器的内容
    $.pjax.reload('#container');

options默认参数说明

参数名 默认值 说明
timeout 650 ajax 超时时间(单位ms),超时后会执行默认的页面跳转,所以超时时间不应过短,不过一般不需要设置
push true 使用window.history.pushState改变地址栏url(会添加新的历史记录)
replace false 使用window.history.replaceState改变地址栏url(不会添加历史记录)
maxCacheLength 20 缓存的历史页面个数(pjax加载新页面前会把原页面的内容缓存起来,缓存加载后其中的脚本会再次执行)
version   是一个函数,返回当前页面的pjax-version,即页面中<meta http-equiv="x-pjax-version">标签内容。使用response.setHeader("X-PJAX-Version", "")设置与当前页面不同的版本号,可强制页面跳转而不是局部刷新。
scrollTo 0 页面加载后垂直滚动距离(与原页面保持一致可使过度效果更平滑)
type "GET" ajax的参数,http请求方式
dataType "html" ajax的参数,响应内容的Content-Type
container   用于查找容器的CSS选择器,[container]参数没有指定时使用
url link.href 要跳转的连接,默认a标签的href属性
target link pjax事件参数e的relatedTarget属性,默认为点击的a标签
fragment   使用响应内容的指定部分(css选择器)填充页面,服务端不进行处理导致全页面请求的时候需要使用该参数,简单的说就是对请求到的页面做截取

pjax失效情况


会有一些情况导致pjax失效,下面结合源码分析下(省略部分无关代码)

function handleClick(event, container, options) {
... // 1. 点击事件的事件源不是a标签。使用a标签可以做到对旧版本浏览器的兼容,所以不建议使用其他标签注册事件
if (link.tagName.toUpperCase() !== 'A')
throw "$.fn.pjax or $.pjax.click requires an anchor element" // 2. 使用鼠标滚轮点击(新标签页打开)
// 点击超链接的同时按下Shift、Ctrl、Alt和Meta(在Windows键盘中是Windows键,在苹果机中是Cmd键)
// 作用分别代表新窗口打开、新标签打开(不切换标签)、下载、新标签打开(切换标签)
if (event.which > 1 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)
return // 3. 跨域(网络通讯协议,域名不一致)
if (location.protocol !== link.protocol || location.hostname !== link.hostname)
return // 4. 当前页面的锚点定位
if (link.href.indexOf('#') > -1 && stripHash(link) == stripHash(location))
return // 5. 已经阻止元素发生默认的行为(url跳转)
if (event.isDefaultPrevented())
return ... var clickEvent = $.Event('pjax:click')
$(link).trigger(clickEvent, [opts]) // 6. pjax:click事件回调中已经阻止元素发生默认的行为(url跳转)
if (!clickEvent.isDefaultPrevented()) {
pjax(opts)
event.preventDefault()// 阻止url跳转
$(link).trigger('pjax:clicked', [opts])
}
}

除了上述情况之外,还有下列几种情况:

  • ajax请求失败,或者timeout后请求被中止
  • 当前页面X-PJAX-Version和请求的新页面版本不一致
  • 请求得到完整的页面(包含html标签)却没设置fragment参数

实际操作中出现问题: 
pajx在浏览器回退和前进是无任何问题的。但如果你进行刷新或F5操作。那么加载出来的页面仅仅为地址栏后台请求出来的页面:比如,如果你的菜单栏项是通过pjax(这里请求的页面dom为 a/list.html)加载对应的内容到指定div(这里假设为div1)。那么如果进行了刷新或F5操作后页面出现的仅仅为 a/list.html页面的布局和信息。如何解决? 
pajx在提交的头信息中包括了 x-pjax: true

  • 1.服务器端判断是否为x-pjax请求

    服务器后台可通过该字段来判断是否为x-pjax请求。或者自己定义好参数传到后台来区分是否是x-pjax的请求。

  • 2.如果不为x-pjax请求则转发到首页地址

    如果你菜单项的首页为index.html 则转发到该页面。那么在刷新后就能够跳转到首页。包含了菜单项等。

@Controller
public class TestController { @RequestMapping("/")
public String index(){
return "index";
} @RequestMapping("/data")
public String test(HttpServletRequest request){
boolean b = Boolean.valueOf(request.getHeader("x-pjax"));
if(b){ }else{
return "redirect:/";
}
return "test";
} }
 

pjax 笔记的更多相关文章

  1. React routerV4 笔记

    React routerV4 笔记     一.基础路由示例 import React from 'react' import { BrowserRouter as Router, Route, Li ...

  2. 在 Laravel 应用中使用 pjax 进行页面加速

    说明# PHPHub 使用 pjax 来加速网页的加载, 这篇文章是在开发完此功能后做的笔记. 什么是 Pjax# .--. / \ ## a a ( '._) |'-- | _.\___/_ ___ ...

  3. git-简单流程(学习笔记)

    这是阅读廖雪峰的官方网站的笔记,用于自己以后回看 1.进入项目文件夹 初始化一个Git仓库,使用git init命令. 添加文件到Git仓库,分两步: 第一步,使用命令git add <file ...

  4. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  5. SQL Server技术内幕笔记合集

    SQL Server技术内幕笔记合集 发这一篇文章主要是方便大家找到我的笔记入口,方便大家o(∩_∩)o Microsoft SQL Server 6.5 技术内幕 笔记http://www.cnbl ...

  6. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  7. PHP-会员登录与注册例子解析-学习笔记

    1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...

  8. NET Core-学习笔记(三)

    这里将要和大家分享的是学习总结第三篇:首先感慨一下这周跟随netcore官网学习是遇到的一些问题: a.官网的英文版教程使用的部分nuget包和我当时安装的最新包版本不一致,所以没法按照教材上给出的列 ...

  9. springMVC学习笔记--知识点总结1

    以下是学习springmvc框架时的笔记整理: 结果跳转方式 1.设置ModelAndView,根据view的名称,和视图渲染器跳转到指定的页面. 比如jsp的视图渲染器是如下配置的: <!-- ...

随机推荐

  1. Android OpenGL ES 入门系列(二) --- 环境搭建

    转载请注明出处 本文出自Hansion的博客 本章介绍如何使用GLSurfaceView和GLSurfaceView.Renderer完成在Activity中的最简单实现. 1.在AndroidMan ...

  2. git上传文件到github

     一.git之上传代码到github. 安装git,这个就不说了,很多帖子都有详细说明.  二.新建仓库,GitHub上的,首先申请账号.  三.本地选择地方新建本地仓库. 建完本地仓库文件夹,在本地 ...

  3. Hadoop源码篇--Client源码

    一.前述 今天起剖析源码,先从Client看起,因为Client在MapReduce的过程中承担了很多重要的角色. 二.MapReduce框架主类 代码如下: public static void m ...

  4. iOS性能优化技术

    小小总结,后续继续跟进. 1. 提高应用性能的几个开发细节 * 尽量避免使用constraint实现动画 * 尽量避免使用数组的删除操作 * 尽量避免使用 NSString::stringWithFo ...

  5. 转自 BotVS 量化平台社区 --- 如何从绩效报告中分辨出“好模型 or 坏模型”

    ## NO:01 在投资行业一直有一个说法,靠交易盈利是所有赚钱方式中最难的一种,以至于有人戏谑称交易为投资领域的搬砖工作. 为了提升交易效率.挖掘潜在投资机会,量化交易伴随着信息技术的发展大行其道, ...

  6. 如何搞定SVN目录的cleanup问题和lock问题

    最近在使用SVN的时候碰到一个问题,就是操作时由于粗心大意,在更新的过程中点击取消,使得该目录出现cleanup的操作提示. OK,按照cleanup提示操作后,又提示目录被lock... 网上有解决 ...

  7. Java设计模式总汇二(小白也要飞)

    PS:上一篇我介绍了适配器设计模式.单例设计模式.静态代理设计模式.简单工厂设计模式,如果没有看过第一篇的小火鸡可以点这个看看http://www.cnblogs.com/cmusketeer/p/8 ...

  8. 【转载】netstat--查看服务器[有效]连接数--统计端口并发数--access.log分析

    简介 Netstat 命令用于显示各种网络相关信息,如网络连接,路由表,接口状态 (Interface Statistics),masquerade 连接,多播成员 (Multicast Member ...

  9. Nginx是如何处理Request的?

    nginx是如何匹配过来的请求,然后做处理的呢?这个匹配的过程可以分为两步: 1.选择server 2.选择location    选择server 仅仅匹配server name 加入Nginx的配 ...

  10. TLD算法原理2--学习理解之(三)

    TLD(Tracking-Learning-Detection)是一种新的单目标长时间(long term tracking)跟踪算法.该算法与传统跟踪算法的显著区别在于将传统的跟踪算法和传统的检测算 ...