pjax是什么
pjax是jquery的一个插件,它使用ajax和pushState两个技术改善用户的网页浏览体验。具体来说,当用户使用a标签切换页面时,可以实现局部刷新的技术。
pjax主要做两方面的事儿:
用户点击链接发送ajax请求,服务器得到请求返回需要填充的HTML片段,客户端得到HTML片段然后插入更新区域页面填充完毕后,使用pushState更新当前的URL这个过程能实现页面局部刷新,比传统的页面切换刷新的体验好一些,因为:只下载需要的HTML页面片段,没有JS、CSS解析如果服务端配置了正确的pjax请求,则只返回要更新的HTML片段,客户端只更新必要的内容,避免了页面重新渲染的过程。

如何使用

  1. 客户端
    客户端设置分两步:
    下载插件,包括jquery1.8+,或者npm安装,这部分参考文档,不赘述。初始化pjax插件,并有条件的拦截a标签跳转。

初始化
$.fn.pjax
下面代码表示:当selector被点击时,执行ajax请求,并将返回的HTML字符串填充在container标记的位置
$(document).pjax(selector, [container], options)

参数说明
selector:click事件的选择器
container:pjax容器id
options :配置参数
pjax options

可以使用下面的方式动态设置options:

$.pjax.defaults.timeout = 1200

初始化一般的做法是做好HTML结构,有条件的触发pjax跳转请求:

<div data-pjax>
    <a data-pjax href="/to/somewhere">ToSomewhere1</a>
    <a data-pjax href="/to/somewhere">ToSomewhere2/a>
</div>
<section id="pjax-container">
    <!-- 在这里更新返回的HTML字符串 -->
</section>

$(document).pjax('[data-pjax] a, a[data-pjax]', '#pjax-container')

  1. 服务端
    服务端也比较简单,监听HTTP的header中有X-PJAX的ajax请求,如果有则返回HTML片段,而不是整个HTML。

API介绍
这部分用于更细粒度的控制。

$.pjax.click

示例:

// 确定能使用pjax时
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提交表单
$.pjax.reload
对当前URL使用pjax的方式重新获取HTML代码片段,并且在指定容器替换,这个过程不添加新的历史记录。(子片段重刷新)

$.pjax.reload('#pjax-container', options)

$.pjax
不是通过click触发pjax的时候使用。比如某些操作后自动触发pjax的过程。如果能获取到click的event事件时,建议使用$.pjax-click(event)替换。

function applyFilters() {
  var url = urlForFilters()
  $.pjax({url: url, container: '#pjax-container'})
}

pjax生命周期

pjax生命周期简单的说:

生命周期和Loading组件使用密切:

$(document).on('pjax:send', function() {
  $('#loading').show()
})
$(document).on('pjax:complete', function() {
  $('#loading').hide()
})

高级技巧
子页面加载完毕初始化其中的插件/组件
pjax只是请求HTML片段之后插入指定位置,因此片段内的JS插件/组件初始化需要在pjax:end事件后执行。

$(document).on('ready pjax:end', function(event) {
  $(event.target).initializeMyPlugin()
})

这段代码会在document ready或者container ready后执行initializeMyPlugin初始化方法(包括前进后退)。

强制reload
当使用pjax导致整个页面被强制刷时,可能的原因是:
当返回的HTML片段包含标签且fragment选择器没有指定时。如果指定了fragment选择器,pjax将从HTML文档中提取需要局部刷新的子片段。服务端返回的内容为空时。

HTTP响应的code是 4xx 或者 5xx。

浏览器重定向
在响应头中设置X-PJAX-URL,例如:

request.headers['X-PJAX-URL'] = "http://example.com/hello"

Layout重新加载
当客户端页面的pjax版本和服务器返回的pjax版本不一致时,页面会重新刷新。
客户端页面的pjax版本:

<meta http-equiv="x-pjax-version" content="v123">

如果服务器修改了版本则重新刷新:
response.headers[‘X-PJAX-Version’] = “xxxx修改版本名称xxxx”

使用建议
这货需要服务端密切配合,如果服务端没设置好,要不就是请求只返回HTML片段,要不每次页面切换都是重新加载页面。
如果服务端无法完成这些配置,只能ajax异步由前端自己拼接HTML来做,建议使用MV*的库来做这部分。