如果你玩過Google+,看到過YouTube的新界面,便會體驗到這個HTML5的新功能。使用pushState + Ajax(pjax),可以實現網頁的ajax加載,同時又能完成URL的改變而沒有網頁跳轉刷新的跡象,就像是改變了網頁的hash(#)一樣。
?
舊的解決方案
曾說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是不能改變網頁標題的哦。
?
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請求輸出專門的內容。
流程圖示意
這個例子的大致過程如下圖所示
?
j Query + 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
?
?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
