History API在各瀏覽器下的支持情況:
不支持 | 4.0+ | 5.0+ | 8.0+ | 不支持 |
---|
比較典型的是GitHub,在點擊代碼文件夾和文件時,會發現它的url地址欄變換了、標題欄變化了、前進後退按鈕也變化了(跟新開了一個新頁面感覺一樣),但體驗起來很平滑(外層框架的內容沒有重新加載,例如:登錄信息、是否關注主人等),然後是ajax載入新內容。
history在HTML4的時代裏,有如下幾個方法和屬性,應該很熟悉:
length、back()、forward()、go([delta])
在HTML5中又添加了兩個方法:
pushState(data, title[,url])、replaceStage(data, this [,url])
需要注意的是在使用replaceStage,傳入的url必須和當前頁的協議、所在域完全相同(即使不同的子域都不行),否則會提示安全錯誤。
更多內容可以參考:
http://diveintohtml5.org/history.html
http://dev.w3.org/html5/spec-author-view/history.html
如果想在兼容其它老瀏覽器,可以使用History.js
這裏寫了一個測試實例,參考至:http://html5demos.com/history
因爲URL變換了,而在刷新的時候頁面又不能進行跳轉,此時需要在自己的web服務器上寫一些規則了(我本機使用的是nginx),在server_name爲meteoric.com的vhost中添加如下規則:
location ~ ^/history/.*$ { rewrite ^/history/.*$ /html5/history/index.html last; }
頁面訪問路徑是:http://meteoric.com/history/
這樣即使我刷新頁面,所有以history開頭的請求,都將轉至http://meteoric.com/history/index.html
/=======/
1、因爲頁面沒有跳轉,所以在點擊鏈接的時候可以使用ajax請求並渲染數據(類似github的效果)
2、進頁面,可以獲取到當前URL,然後正則取出histroy其後的內容,判定加載哪一種資源
頁面完整的HTML代碼:
<!DOCTYPE html> <html> <head> <meta charset=utf-8 /> <meta name="viewport" content="width=620" /> <title>HTML5__History API</title> <style> body { font: normal 16px/20px "Helvetica Neue", Helvetica, sans-serif; background: rgb(237, 237, 236); margin: 0; margin-top: 40px; padding: 0; } section, header, footer { display: block; } #wrapper { width: 600px; margin: 0 auto; background-color: #fff; -moz-border-radius: 10px; -webkit-border-radius: 10px; border-radius: 10px; border-top: 1px solid #fff; padding-bottom: 76px; } h1 { padding-top: 10px; } h2 { font-size: 100%; font-style: italic; } header, article > *, footer > * { margin: 20px; } footer > * { margin: 20px; color: #999; } #status { padding: 5px; color: #fff; background: #ccc; } #status.fail { background: #c00; } #status.success { background: #0c0; } #status.offline { background: #c00; } #status.online { background: #0c0; } li { margin-bottom: 10px; } #examples { padding-left: 20px; } #examples li { list-style: square; padding: 0; margin: 0; } </style> </head> <body> <section id="wrapper"> <article> <p id="status">HTML5 History API not supported</p> <p>最後一次觸發的事件: <em><span id="lastevent">(none)</span></em></p> <p>點擊下面的鏈接進行測試,點擊後頁面的URL發生變化,但重新刷新後依舊停留於此頁面。</p> <p>可以使用瀏覽器原生的前進、後退按鈕</p> <ul id="examples"> <li><a href="/history/first">first</a></li> <li><a href="/history/second">second</a></li> <li><a href="/history/third">third</a></li> <li><a href="/history/fourth">fourth</a></li> </ul> <div id="output"></div> </article> </section> <script> 1: 2: 3: var addEvent = (function () { 4: if (document.addEventListener) { 5: return function (el, type, fn) { 6: if (el && el.nodeName || el === window) { 7: el.addEventListener(type, fn, false); 8: } else if (el && el.length) { 9: for (var i = 0; i < el.length; i++) { 10: addEvent(el[i], type, fn); 11: } 12: } 13: }; 14: } else { 15: return function (el, type, fn) { 16: if (el && el.nodeName || el === window) { 17: el.attachEvent('on' + type, function () { return fn.call(el, window.event); }); 18: } else if (el && el.length) { 19: for (var i = 0; i < el.length; i++) { 20: addEvent(el[i], type, fn); 21: } 22: } 23: }; 24: } 25: })(); 26: 27: 28: 29: 30: var $ = function (s) { return document.getElementById(s); }, 31: state = $('status'), 32: lastevent = $('lastevent'), 33: urlhistory = $('urlhistory'), 34: examples = $('examples'), 35: output = $('output'), 36: template = '<p>URL: <strong>{url}</strong>, name: <strong>{name}</strong>, location: <strong>{location}</strong></p>', 37: data = { // imagine these are ajax requests :) 38: first : { 39: name: "張三", 40: location: "北京" 41: }, 42: second: { 43: name: "李四", 44: location: "上海" 45: }, 46: third: { 47: name: "王五", 48: location: "重慶" 49: }, 50: fourth: { 51: name: "小六", 52: location: "江蘇,南京" 53: } 54: }; 55: 56: function reportEvent(event) { 57: lastevent.innerHTML = event.type; 58: } 59: 60: function reportData(data) { 61: output.innerHTML = template.replace(/(:?\{(.*?)\})/g, function (a,b,c) { 62: return data[c]; 63: }); 64: } 65: 66: //檢測瀏覽器對此特性的支持情況 67: !(function() { 68: if (typeof history.pushState === 'undefined') { 69: state.className = '當前瀏覽器不支持HTML5 History API'; 70: } else { 71: state.className = 'success'; 72: state.innerHTML = '當前瀏覽器支持HTML5 History API'; 73: } 74: })(); 75: 76: addEvent(examples, 'click', function (event) { 77: var title; 78: 79: event.preventDefault(); 80: if (event.target.nodeName == 'A') { 81: title = event.target.innerHTML; 82: data[title].url = event.target.getAttribute('href'); // slightly hacky (the setting), using getAttribute to keep it short 83: history.pushState(data[title], title, event.target.href); 84: reportData(data[title]); 85: } 86: }); 87: 88: addEvent(window, 'popstate', function (event) { 89: var data = event.state; 90: reportEvent(event); 91: reportData(event.state || { url: "unknown", name: "undefined", location: "undefined" }); 92: }); 93: 94: addEvent(window, 'hashchange', function (event) { 95: reportEvent(event); 96: }); 97: 98: addEvent(window, 'pageshow', function (event) { 99: reportEvent(event); 100: }); 101: 102: addEvent(window, 'pagehide', function (event) { 103: reportEvent(event); 104: }); 105: </script> </body> </html>
因爲需要web服務器的支持,所以上述效果無法在blog中進行預覽。需有興趣,可搭建一個簡單的環境進行測試~
如果有興趣瀏覽兼容ie6+(無定時器)的history,可以閱讀人人網前端開發人員的這篇文章:http://jingwei.li/blog/?p=183
之前我也寫過一篇相關的文章:”不使用定時器實現的onhashchange”,代碼有參閱人人網前臺腳本(一時好奇就右擊源碼大致掃了一下)