1. 程式人生 > >將網站打造成單頁面應用SPA(Single Page Application)

將網站打造成單頁面應用SPA(Single Page Application)

摘要:不知你有沒有發現,像Github、百度、微博等這些大站,已經不再使用普通的a標籤做跳轉了。他們大多使用Ajax請求替代了a標籤的預設跳轉,然後使用HTML5的新API修改了Url,你可以在F12的Network面板裡發現這個祕密。

前言

不知你有沒有發現,像Github、百度、微博等這些大站,已經不再使用普通的a標籤做跳轉了。他們大多使用Ajax請求替代了a標籤的預設跳轉,然後使用HTML5的新API修改了Url,你可以在F12的Network面板裡發現這個祕密。

這項技術並沒有特別標準的學名,大家都稱呼為Pjax,意為PushState + Ajax。這並不完全準確,因為還有Hash + Ajax等方法,但為了方便,我們下文還是統稱為Pjax。

為什麼要這麼做?

Pjax是一個優秀的解決方案,你有足夠多的理由來使用它:

  • 可以在頁面切換間平滑過渡,增加Loading動畫。
  • 可以在各個頁面間傳遞資料,不依賴URL。
  • 可以選擇性的保留狀態,如音樂網站,切換頁面時不會停止播放歌曲。
  • 所有的標籤都可以用來跳轉,不僅僅是a標籤。
  • 避免了公共JS的反覆執行,如無需在各個頁面開啟時都判斷是否登入過等等。
  • 減少了請求體積,節省流量,加快頁面響應速度。
  • 平滑降級到低版本瀏覽器上,對SEO也不會有影響。

原理呢?

Pjax的原理十分簡單。

  1. 攔截a標籤的預設跳轉動作。

  2. 使用Ajax請求新頁面。

  3. 將返回的Html替換到頁面中。

  4. 使用HTML5的History API或者Url的Hash修改Url。
    HTML5 History API

我們來看看HTML5在History裡增加了什麼:

history.pushState(state, title, url)

pushState方法會將當前的url新增到歷史記錄中,然後修改當前url為新url。請注意,這個方法只會修改位址列的Url顯示,但並不會發出任何請求。我們正是基於此特性來實現Pjax。它有3個引數:

state: 可以放任意你想放的資料,它將附加到新url上,作為該頁面資訊的一個補充。
title: 顧名思義,就是document.title。不過這個引數目前並無作用,瀏覽器目前會選擇忽略它。
url: 新url,也就是你要顯示在位址列上的url。

history.replaceState(state, title, url)

replaceState方法與pushState大同小異,區別只在於pushState會將當前url新增到歷史記錄,之後再修改url,而replaceState只是修改url,不新增歷史記錄。

window.onpopstate //事件

一般來說,每當url變動時,popstate事件都會被觸發。但若是呼叫pushState來修改url,該事件則不會觸發,因此,我們可以把它用作瀏覽器的前進後退事件。該事件有一個引數,就是上文pushState方法的第一個引數state。

一個例項:

這裡我們以daipig為例,開啟daipig,位址列是 http://www.daipig.com 。接下來開啟F12 Console,輸入:

history.pushState({ a: 1, b: 2 }, null,"http://www.daipig.com/abcdefg"); 

可以發現,url已經變成我們輸入的url了,但頁面並沒有重新整理,也沒有發出任何請求。現在再輸入history.state,就可以看到我們剛剛傳過來的第一個引數state了。

這時點選後退,url會回到www.daipig.com,同樣是沒有重新整理。只不過後退的時候其實是觸發了window.onpopstate事件的。