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
key | default | description |
---|---|---|
timeout |
650 | ajax請求如果超時將觸發強制刷新 |
push |
true | 使用 [pushState][] 在瀏覽器中添加導航記錄 |
replace |
false | 是否使用replace方式改變URL |
maxCacheLength |
20 | 返回的HTML片段字符串最大緩存數 |
version |
當前pjax版本 | |
scrollTo |
0 | 當頁面導航切換時滾動到的位置. 如果想頁面切換不做滾動重置處理,請傳入false . |
type |
"GET" |
使用ajax的模板請求方法,參考 $.ajax |
dataType |
"html" |
模板請求時的type,參考 $.ajax |
container |
內容替換的CSS選擇器 | |
url |
link.href | 用于ajax請求的url,可以是字符串或者返回字符串的函數 |
target |
link | eventually the relatedTarget value for pjax events
|
fragment |
從服務端返回的HTML字符串中子內容所在的CSS選擇器,用于當服務端返回了整個HTML文檔,但要求pjax局部刷新時使用。 |
可以使用下面的方式動態設置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')
2. 服務端
服務端也比較簡單,監聽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提交表單
$(document).on('submit', 'form[data-pjax]', function(event) {
$.pjax.submit(event, '#pjax-container')
})
$.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片段包含
<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*的庫來做這部分。