標籤:blog http io os 使用 ar strong div sp
如果你玩過Google+,看到過YouTube的新介面,便會體驗到這個HTML5的新功能。使用pushState + Ajax(pjax),可以實現網頁的ajax載入,同時又能完成URL的改變而沒有網頁跳轉重新整理的跡象,就像是改變了網頁的hash(#)一樣。
指引 / 跳至
- 1 舊的解決方案
- 2 新的解決方案: pushState
- 2.1 HTML5 的 pushState+Ajax
- 2.2 pushState 例子
- 2.3 Demo 示範
- 2.4 replaceState 同理
- 2.5 pushState、replaceState 的區別
- 3 限制因素
- 4 Ajax 配合 pushState 例子
- 5 pushState 配合 popstate 監聽
- 6 jQuery + PJAX 外掛程式
舊的解決方案
曾說SEO和ajax是天敵。此前從Twitter開始流行Ajax+hash的方式調用內容,Google給出的解決方案是“#!~string”自動轉換為“?_excaped_fragment_=~string”來抓取動態內容。但這無疑會非常麻煩:首先你需要對網站進行“?_excaped_fragment_=~string”的處理配置,而且,如果使用者把網址“http://example.com/#!/~string”直接複製並分享的話,意味著網頁還必須監聽hashchange。不過如果你覺得這個#!很好看就沒關係了。
新的解決方案: pushState
然而HTML5的新介面pushState / replaceState就可以比較完美的解決問題,它避免了改變hash的問題,避免了使用者不理解URL的形式感到疑惑,同時還有onpopstate提供監聽,良好響應後退前進。而且它不需要這個URL真實存在。
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調用風格。以jQuery為例,為了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請求輸出專門的內容。
流程圖示意
這個例子的大致過程如所示
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})
});}
謝謝收看,如有不正請指出。
http://blog.netsh.org/posts/pushstate-ajax_1339.netsh.html
不重新整理改變URL: pushState + Ajax