告别定时器,兼容IE实现onhashchange
不使用定时器,让ajax实现历史记录功能。
兼容性:FF3.0+、IE6+、Chrome
源码大小:1.76KB(未压缩),下载地址见文末。
常用ajax的同学应该对onhashchange并不陌生,ajax并不是一个完美的东西,无刷新的页面会导致我们丢失本该有的浏览器历史记录,通常我们需要通过url hash来手动的产生浏览器历史记录,从而使“后退”/“前进”按钮有效。所以,还没有关注这点的同学也需要注意onhashchange了,有“后退”/“前进”功能的页面才是一个好页面。
遗憾的是onhashchange事件是html5里新增加的,所以一些古老的浏览器并不支持它,目前的支持情况如下(via):
IE 的部份,IE8 之后才有支持:「onhashchange Event」
Firefox 则是 3.6 之后才有支持:「window.onhashchange」
Webkit 是 528 版以后 (2009/08/07 的 ticket):「Support for HTML5 "hashchange" event」,对应的版本是 Google Chrome 1.0.154 之后,以及 Safari 4.0+
对于不支持的浏览器,可以使用隐藏的iframe来达到更改浏览器历史记录的目的。
HistoryManager.js源码如下:
function HistoryManager() { this.listener = null; this.adapterIframe = null; this._initialize(); } ~(function() { var flag = false, isIE = !!window.ActiveXObject && /msie (\d)/i.test(navigator.userAgent) ? RegExp['$1'] : false, pointer = this; this.makeIEHistory = function(url) { if (!url) { return ; } var frameDoc = pointer.adapterIframe.contentWindow.document; frameDoc.open(); frameDoc.write([ "<html>", "<head>", "<script type='text/javascript'>", "function pageLoaded() {", "try {top.window.historyManager.fireOnHashChange(\""+url+"\");} catch(ex) {}", "}", "</script>", "</head>", "<body onload='pageLoaded();'>", "<input type='value' value='"+url+"' id='history'/>", "</body>", "</html>" ].join("")); frameDoc.title = document.title; frameDoc.close(); } this.fireOnHashChange = function(url) { location.hash = "#" + url.replace(/^#/, ""); if (window.onhashchange) { window.onhashchange(); } } this.add = function(url) { flag = true; if (isIE && isIE < 8) { pointer.makeIEHistory(url); } else { location.hash = "#" + url.replace(/^#/, ""); } } this.fire = function(url) { if (!url) { url = document.location.hash.slice(1); } pointer.listener(url); } this.addListener = function(fn) { pointer.listener = typeof fn === 'function' ? fn : function() {}; } this._initialize = function() { if (isIE && isIE < 8) { pointer.adapterIframe = document.getElementById("HISTORY_ADAPTER"); pointer.makeIEHistory(); } window.onhashchange = function() { if (flag) { flag = false; return ; } pointer.fire(); } } }).call(HistoryManager.prototype);
测试html源码如下:
<!DOCTYPE HTML> <html> <head> <title>ajax历史记录</title> <meta name="keywords" content="" /> <meta name="description" content="" /> <meta http-equiv="content-type" content="text/html;charset=utf-8"> <style type="text/css"> a {display:inline-block; margin-right:10px;} #clickHistory {border:1px solid #406c99; padding:15px; margin-top:10px; width:600px;} </style> </head> <body> <!--[if IE]> <iframe id="HISTORY_ADAPTER" src="ajaxhistory.html" style="display:none"></iframe> <![endif]--> <a href="#111.html"> Test1 </a> <a href="#222.html"> Test2 </a> <a href="#333.html"> Test3 </a> <div id="clickHistory"> 默认页面 </div> <script type="text/javascript" src="jquery-1.11.1.min.js"></script> <script type="text/javascript" src="HistoryManager.js"> </script> <script type="text/javascript"> var historyManager = new HistoryManager(); historyManager.addListener(function () { var url = arguments[0]; alert("当前的改变后的URL:" + url); setHashHistory(url); }); document.onclick = function (ev) { ev = ev || window.event; var elem = ev.srcElement || ev.target; if (elem.tagName && elem.tagName.toLowerCase() == "a") { if (ev.preventDefault) { ev.preventDefault(); } else { ev.returnValue = false; } var href = elem.getAttribute("href", 2); historyManager.add(href); setHashHistory(href); } } function setHashHistory(_url) { //这里可以当前要显示的网址,通过ajax请求网址得到页面并显示 $.ajax({ url : _url.replace(/^#/, ''), success: function(data){ $("#clickHistory").html(data); }, error: function(XMLHttpRequest, textStatus, errorThrown){ $("#clickHistory").html(errorThrown); } }) } $(document).ready(function(){ if(location.hash){ setHashHistory(location.hash); } }) </script> </body> </html>
3个html嵌入页面源码如下:
<font color="#2B6088">I am the #111 ajax container..</font>
<font color="#FD1B15">I am the #222 ajax container..</font>
<font color="#FF6D06">I am the #333 ajax container..</font>
chrome和firefox下的不贴图了,只贴IE6下的:
初始页面:
按顺序点击Test1,Test2,Test3之后:
很明显,333.html被load到div中了,然后点击IE6的后退按钮:
这时再点击确定,会发现历史记录中的222.html被load回来。
就是这么简单,感谢meteoric_cry的代码。
源码和测试文件下载地址:
注意:本测试案例必须在网站目录下测试,引入了jquery的ajax加载页面功能,在桌面测试无效哦。
本文地址:http://blog.zhengshuiguang.com/js/onhashchange.html
转载随意,但请附上文章地址:-)
评论已关闭