1. 程式人生 > >使用pushState()改變url而不重新整理

使用pushState()改變url而不重新整理

編者注:這個pushState()是一個HTML5的新介面,你可能在一些科技部落格如36kr上看到過,ajax載入新的文章,並且改變網址卻不需要重新整理頁面,本站也用到了這個,當你在首頁往下拉時,載入分頁內容,網址也隨著改變,有利於後退和增加使用者體驗。

HTML5 的 pushState+Ajax

HTML5提供history介面,把URL以state的形式新增或者替換到瀏覽器中,其實現函式正是 pushState 和 replaceState。

pushState 例子

pushState() 的基本引數是:

window.history.pushState(state, title, url);

其中state和title都可以為空,但是推薦不為空,應當建立state來配合popstate監聽。

例如,我們通過pushState現改變URL而不重新整理頁面。

var state = ( {

url: ~href, title: ~title, ~additionalKEY: ~additionalVALUE

} );

window.history.pushState(state, ~title, ~href);

其中帶有“~”符號的是自定義內容。就可以把這個~href(URL)推送到瀏覽器的歷史裡。如果想要改變網頁的標題,應該:

document.title= ~newTitle
;

注意只是pushState是不能改變網頁標題的哦。

Demo 演示

 (實現函式onclick = history.pushState( null, null, '/test-string'); )。實際上這個部落格在文章之間也部署了這個技術。

replaceState 同理

window.history.replaceState( state, ~title, ~href);

pushState、replaceState 的區別

pushState()可以建立歷史,可以配合popstate事件,而replaceState()則是替換掉當前的URL,不會產生歷史。

限制因素

只能用同域的URL替換,例如你不能用http://baidu.com去替換http://google.com。而且state物件不儲存不可序列化的物件如DOM。

Ajax 配合 pushState 例子

現在用Ajax + pushState來提供全新的ajax呼叫風格。以為例,為了seo需要,應該為a標籤的onclick新增方法。

$("~target a").click(function(evt){

evt.preventDefault(); // 阻止預設的跳轉操作

var uri=$(this).attr('href');

var newTitle=ajax_Load(uri); // 你自定義的Ajax載入函式,例如它會返回newTitle

document.title=newTitle; // 分配新的頁面標題

if(history.pushState){

var state=({

url: uri, title: newTitle

});

window.history.pushState(state, newTitle, uri);

}else{ window.location.href="#!"+~fakeURI; } // 如果不支援,使用舊的解決方案

return false;

});

function ajax_Load(uri){ ... return newTitle; } // 你自定義的ajax函式,例如它會返回newTitle

即可完成pushState。至於新標題newTitle的獲取就是另外的問題了,例如你可以為a標籤分配data-newtitle=~title屬性並屆時讀取,或者如果你用的$.ajax()函式,可以用$(result).filter("title").text()來獲取。

另外如果需要對新載入的頁面的連線同樣使用這個ajax,則需要對新內容的a標籤重新部署,例如

$("~newContentTarget a").click(function(evt){ ... });

pushState 配合 popstate 監聽

想要良好的支援瀏覽器的歷史前進後退操作,應當部署popstate監聽:

window.addEventListener('popstate', function(evt){

var state = evt.state;

var newTitle = ajax_Load(state.url); //你自定義的ajax載入函式,例如它會返回newTitle

document.title=newTitle;

}, false);

提醒,你可以通過setRequestHeader()來讓伺服器端配合你的ajax請求輸出專門的內容。

流程圖示意

這個例子的大致過程如下圖所示

ajax-pushstate-example

jQuery + PJAX 外掛

已經在github上釋出,有人把PJAX做成了jQuery外掛,方便呼叫,節省大量程式碼:

if ($.support.pjax) {

$(document).on('click', 'a[data-pjax]', function(event) {

var container = $(this).closest('[data-pjax-container]')

$.pjax.click(event, {container: container})

});}

謝謝收看,如有不正請指出。