之前也没有研究过pjax,但是没事走访别人博客时看到不少经过pjax优化的网站,响应速度很快,今天看到玖梦博客的一篇《一行代码实现全站pjax无刷新加载》测试后发发现效果确实不错,故发文记录一下。
pjax是什么
pjax是一个jQuery插件,它通过ajax和pushState技术提供了极速的(无刷新ajax加载)浏览体验,并且保持了真实的地址、网页标题,浏览器的后退(前进)按钮也可以正常使用。
pjax的工作原理是通过ajax从服务器端获取HTML,在页面中用获取到的HTML替换指定容器元素中的内容。然后使用pushState技术更新浏览器地址栏中的当前地址。
以下两点原因决定了pjax会有更快的浏览体验:
- 不存在页面资源(js/css)的重复加载和应用;
- 如果服务器端配置了pjax,它可以只渲染页面局部内容,从而避免服务器渲染完整布局的额外开销。
项目现状
jquery-pjax的维护方向:可能会继续修复重要的bug,但其功能不会再发生变化,即不会再实现新功能,也不会再扩展现有功能。
如何使用
1. 客户端
客户端设置分两步:
- 下载插件,包括jquery1.8+,或者npm安装,这部分参考文档,不赘述。
- 初始化pjax插件,并有条件的拦截
a
标签跳转。
初始化
$.fn.pjax
下面代码表示:当selector
被点击时,执行ajax请求,并将返回的HTML字符串填充在container
标记的位置。
$(document).pjax(selector, [container], options)
参数说明
- selector:string类型,用于click 事件委托 的选择器。
- container:string类型,用于标识唯一pjax容器的选择器。
- options object类型,包含下列选项。
pjax配置选项
选项 | 默认值 | 说明 |
---|---|---|
timeout | 650 | ajax超时时间(毫秒),超时后强制刷新整个页面 |
push | true | 使用 pushState 在浏览器中添加历史记录 |
replace | false | 替换URL地址但不添加浏览器历史记录 |
maxCacheLength | 20 | 容器元素缓存内容的最大值(次) |
version | string或function,返回当前pjax版本 | |
scrollTo | 0 | 浏览器滚动条的垂直滚动位置。设为false 时禁止滚动 |
type | “GET” | 参考 $.ajax |
dataType | “html” | 参考 $.ajax |
container | 被替换内容元素的CSS选择器 | |
url | link.href | string或function,返回ajax请求响应的URL |
target | link | pjax 事件 中 relatedTarget 属性的最终值 |
fragment | css选择器,提取ajax响应内容中指定的内容片段 |
可以在全局使用$.pjax.defaults对象改变默认配置:
$.pjax.defaults.timeout = 1200
2. 服务端
服务端也比较简单,监听HTTP的header中有X-PJAX
的ajax请求,如果有则返回HTML片段,而不是整个HTML。
API介绍
这部分用于更细粒度的控制。
$.fn.pjax
最简单常见的pjax使用方法如下:
$(document).pjax('a', '#pjax-container')
通过这种方式可以让页面中所有的链接都实现pjax加载,并指定#pjax-container作为容器元素。
$.pjax.click
这是一个$.fn.pjax内部使用的底层方法,通过此方法可以在pjax事件之上做更多的事情。本示例使用当前的click上下文来设置一个祖先元素作为容器:
if ($.support.pjax) { $(document).on('click', 'a[data-pjax]', function(event) { var container = $(this).closest('[data-pjax-container]') var containerSelector = '#' + container.id $.pjax.click(event, {container: containerSelector}) }) }
$.pjax.submit
通过pjax提交表单。
$(document).on('submit', 'form[data-pjax]', function(event) { $.pjax.submit(event, '#pjax-container') })
$.pjax.reload
使用pjax机制发起一个当前URL的请求到服务器,并且通过响应的内容替换容器元素中的内容,同时不添加浏览器历史记录。
$.pjax.reload('#pjax-container', options)
$.pjax
手动调用pjax。主要用于非click事件发起pjax请求的情况。
function applyFilters() { var url = urlForFilters() $.pjax({url: url, container: '#pjax-container'}) }
事件
除了pjax:click和pjax:clicked,其他所有pjax事件都是在pjax容器元素上触发的。
事件 | 取消 | 参数 | 说明 |
---|---|---|---|
pjax链接事件的生命周期 | |||
pjax:click | ✔︎ | options | 链接被激活的时候触发;取消的时候阻止pjax |
pjax:beforeSend | ✔︎ | xhr, options | 可以设置XHR头 |
pjax:start | xhr, options | ||
pjax:send | xhr, options | ||
pjax:clicked | options | pjax通过链接点击已经开始之后触发 | |
pjax:beforeReplace | contents, options | 从服务器端加载的HTML内容完成之后,替换当前内容之前 | |
pjax:success | data, status, xhr, options | 从服务器端加载的HTML内容替换当前内容之后 | |
pjax:timeout | ✔︎ | xhr, options | 在options.timeout 之后触发;除非被取消,否则会强制刷新页面 |
pjax:error | ✔︎ | xhr, textStatus, error, options | ajax请求出错;除非被取消,否则会强制刷新页面 |
pjax:complete | xhr, textStatus, options | 无论结果如何,都在ajax响应完成后触发 | |
pjax:end | xhr, options | ||
浏览器前进后退事件的生命周期 | |||
pjax:popstate | direction 事件的属性: “back”/”forward” |
||
pjax:start | null, options | 内容替换之前 | |
pjax:beforeReplace | contents, options | 在用缓存中的内容替换HTML之前 | |
pjax:end | null, options | 替换内容之后 | |
pjax:callback | null, options | 页面脚本加载完成后(Admui项目) |
如果您使用了加载指示(如loading图标或“加载中”的文字),pjax:send和pjax:complete这两个事件会比较有用。它们只有在XHR请求(而不是从缓存中加载内容)时才会被触发:
$(document).on('pjax:send', function() { $('#loading').show() }) $(document).on('pjax:complete', function() { $('#loading').hide() })
以下是禁用 pjax:timeout 事件的示例。
$(document).on('pjax:timeout', function(event) { // Prevent default timeout redirection behavior event.preventDefault() })