pjax 筆記

PJAX的基本思路是,用戶點擊一個連接,經過ajax更新頁面變化的部分,而後使用HTML5的pushState修改瀏覽器的URL地址,這樣有效地避免了整個頁面的從新加載。若是瀏覽器不支持history的兩個新API或者JS被禁用了,那這個連接就只能跳轉並從新刷新整個頁面了。和傳統的ajax設計稍微不一樣,ajax一般是從後臺獲取JSON數據,而後由前端解析渲染,而PJAX請求的是一個在服務器上生成好的HTML碎片.css

客戶端向服務器發送一個普通的請求(1),其實也就是點擊了一個連接,服務器會相應這個請求(2),返回一個html文檔。客戶端向服務器發送一個有PJAX標誌的請求(3),此時服務器只返回一個html碎片(4)。可是這兩次請求都讓客戶端的URL變化了,但願上面的說明可讓你明白了PAJX和AJAX的區別了。html

 

用法

  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])
    }
}

 

除了上述狀況以外,還有下列幾種狀況:jquery

  • ajax請求失敗,或者timeout後請求被停止
  • 當前頁面X-PJAX-Version和請求的新頁面版本不一致
  • 請求獲得完整的頁面(包含html標籤)卻沒設置fragment參數

 
實際操做中出現問題: 
pajx在瀏覽器回退和前進是無任何問題的。但若是你進行刷新或F5操做。那麼加載出來的頁面僅僅爲地址欄後臺請求出來的頁面:好比,若是你的菜單欄項是經過pjax(這裏請求的頁面dom爲 a/list.html)加載對應的內容到指定div(這裏假設爲div1)。那麼若是進行了刷新或F5操做後頁面出現的僅僅爲 a/list.html頁面的佈局和信息。如何解決? 
pajx在提交的頭信息中包括了 x-pjax: truegit

  • 1.服務器端判斷是否爲x-pjax請求github

    服務器後臺可經過該字段來判斷是否爲x-pjax請求。或者本身定義好參數傳到後臺來區分是不是x-pjax的請求。ajax

  • 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";
    }

}
相關文章
相關標籤/搜索