专栏首页游戏杂谈不使用定时器实现的onhashchange

不使用定时器实现的onhashchange

之前看sparks345 写的《不采用interval方式模仿onHashChange

后来自己又折腾了一把,完整的源码总共大小是1.66KB(2K不到)

支持:FF3.0+、IE6+、Chrome

主流的浏览器(IE6、IE7除外),基本上都支持onhashchange事件,而IE8也将支持。只有IE6、IE7不支持,而使用这两个浏览器的用户还是占有很大的一部分份额。

网上流传的实现onhashchange方法基本上都采用setInterval来跑,这样做:

第一:不切换也要去检测一次hash,总觉得别扭;

第二:点击过快的时候容易出bug(曾经耿耿于怀这个)

既然外面的轮子都不好用,还就自己造一个吧~

其实造也不难,因需要专门针对ie做一些处理就好了。页面放个iframe,然后然后iframe里面的内容,比如加个表单元素input并监听其onload事件,然后回调。

说明一下:这个方法不是我最先想到的,是我不经意见研究某站点的代码发现的,在这里先致谢一下。

HistoryManager.js的源码:

1: function HistoryManager() {

       2:     this.listener = null;

       3:     this.adapterIframe = null;

       4:     this._initialize();

       5: }

       6:  

       7: ~(function() {

       8:     var flag = false,

       9:         isIE = !!window.ActiveXObject && /msie (\d)/i.test(navigator.userAgent) ? RegExp['$1'] : false,

      10:         $pointer = this;

      11:     

      12:     this.makeIEHistory = function(url) {

      13:         if (!url) {

      14:             return ;

      15:         }

      16:         

      17:         var frameDoc = $pointer.adapterIframe.contentWindow.document;

      18:         

      19:         frameDoc.open();

      20:         frameDoc.write([

      21:             "<html>",

      22:                 "<head>",

      23:                     "<script type='text/javascript'>",

      24:                         "function pageLoaded() {",

      25:                             "try {top.window.historyManager.fireOnHashChange(\""+url+"\");} catch(ex) {}",

      26:                         "}",

      27:                     "</script>",

      28:                 "</head>",

      29:                 "<body onload='pageLoaded();'>",

      30:                     "<input type='value' value='"+url+"' id='history'/>",

      31:                 "</body>",

      32:             "</html>"

      33:         ].join(""));

      34:         frameDoc.title = document.title;

      35:         frameDoc.close();

      36:     }

      37:  

      38:     this.fireOnHashChange = function(url) {

      39:         location.hash = "#" + url.replace(/^#/, "");

      40:         

      41:         if (window.onhashchange) {

      42:             window.onhashchange();

      43:         }

      44:     }

      45:  

      46:     this.add = function(url) {

      47:         flag = true;

      48:  

      49:         if (isIE && isIE < 8) {

      50:             $pointer.makeIEHistory(url);

      51:         } else {

      52:             location.hash = "#" + url;

      53:         }

      54:     }

      55:  

      56:     this.fire = function(url) {

      57:         if (!url) {

      58:             url = document.location.hash.slice(1);

      59:         }

      60:  

      61:         $pointer.listener(url);

      62:     }

      63:  

      64:     this.addListener = function(fn) {

      65:         $pointer.listener = typeof fn === 'function' ? fn : function() {};

      66:     }

      67:  

      68:     this._initialize = function() {

      69:         if (isIE && isIE < 8) {

      70:             $pointer.adapterIframe = document.getElementById("HISTORY_ADAPTER");

      71:             $pointer.makeIEHistory();

      72:         }

      73:  

      74:         window.onhashchange = function() {

      75:             if (flag) {

      76:                 flag = false;

      77:                 return ;

      78:             }

      79:  

      80:             $pointer.fire();

      81:         }

      82:     }

      83:  

      84: }).call(HistoryManager.prototype);

使用方法,初始化一个实例,然后设置监听器,等待点击浏览器的“前进”、“后退”回调便可。

运行示例代码(初次加载可能无法下载脚本,刷新即可~):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>ajax历史记录</title> <meta name="generator" content="editplus" /> <meta name="author" content="" /> <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="#/1111/kk.html">Test1</a><a href="#/2222/kk.html">Test2</a><a href="#/3333/kk.html">Test3</a> <div id="clickHistory">I am the #1 ajax container..</div> <span id="preserve157d83c800624b7cb65a76bef93c4808" class="wlWriterPreserve"></span> <span id="preserve8682e3b47ba64be5b18f76d0a35a767d" class="wlWriterPreserve"></span> </body> </html> 预览代码

测试用的HTML源代码:

1: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

       2: <html>

       3:  <head>

       4:   <title>ajax历史记录</title>

       5:   <meta name="generator" content="editplus" />

       6:   <meta name="author" content="" />

       7:   <meta name="keywords" content="" />

       8:   <meta name="description" content="" />

       9:   <meta http-equiv="content-type" content="text/html;charset=utf-8">

      10:   <style type="text/css">

      11:     a {display:inline-block; margin-right:10px;}

      12:     #clickHistory {border:1px solid #406c99; padding:15px; margin-top:10px; width:600px;}

      13:   </style>

      14:  </head>

      15:  

      16:  <body>

      17:  

      18:     <!--[if IE]><iframe id="HISTORY_ADAPTER" src="ajaxhistory.html" style="display:none"></iframe><![endif]-->

      19:   <a href="#/1111/kk.html">Test1</a><a href="#/2222/kk.html">Test2</a><a href="#/3333/kk.html">Test3</a>

      20:  

      21: <div id="clickHistory">I am the #1 ajax container..</div>

      22:  

      23:   <script type="text/javascript" src="http://files.cnblogs.com/meteoric_cry/historyFrame.js"></script>   1:     2:   <script type="text/javascript">   3:     var historyManager = new HistoryManager();   4:     5:     historyManager.addListener(function() {   6:         var url = arguments[0];   7:     8:         alert("当前的改变后的URL:" + url);   9:           10:         setHashHistory(url);  11:     });  12:    13:     document.onclick = function(ev) {  14:         ev = ev || window.event;  15:         var elem = ev.srcElement || ev.target;  16:    17:         if (elem.tagName && elem.tagName.toLowerCase() == "a") {  18:             if (ev.preventDefault) {  19:                 ev.preventDefault();      20:             } else {  21:                 ev.returnValue = false;  22:             }  23:               24:             var href = elem.getAttribute("href", 2);  25:             historyManager.add(href);  26:    27:             setHashHistory(href);  28:         }  29:     }  30:    31:     function setHashHistory(_url) {  32:         var tid = _url.replace(/[^\/]?\/(\d+)\/(.*)/, "$1");  33:         var colorConfig = {  34:             '1111' : '#2B6088',  35:             '2222' : '#FD1B15',  36:             '3333' : '#FF6D06'  37:         }  38:           39:         var elem = document.getElementById("clickHistory");  40:         var html = elem.innerText || elem.contextText;  41:    42:         elem.innerHTML = html.replace(/\#(\d+)\s/, "#" + tid + " ");  43:         elem.style.backgroundColor = colorConfig[tid];  44:     }      45:   </script>

      24:  </body>

      25: </html>

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Nginx中的PHP缓冲问题

    按代码理解似乎应该是每过1秒钟,将输出一个数字,从10~1 (运行时间>10ms)

    meteoric
  • QQ空间的JSONP示例

    根据Velocity的演讲“性能优化无未日--Qzone首页性能优化2012篇”写的一个例子

    meteoric
  • JavaScript与ActionScript3 -- setTimeout方法的差异

    JavaScript中setTimeout方法接受的参数只有两个,而ActionScript3却可以有多个。

    meteoric
  • 【无人驾驶量产得靠128线廉价激光雷达,中国将是最大市场】专访Velodyne自动驾驶VP

    作者:胡祥杰 闻菲 【新智元导读】Velodyne 激光雷达(64线)曾定价7万多美元,被认为是无人驾驶走向商用不得不解决的成本问题。近日,Velodyne...

    新智元
  • CentOS 7 Tomcat服务的安装与配置

    Java是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由Sun Microsystems公司于1995年5月推出的Java程序设计语言和Java平台(...

    菲宇
  • 详细grep、sed、awk

    [root@VM_0_7_centos tmp]# cat 1.txt 1 2 3 4 5 6 [root@VM_0_7_centos tmp]# cat 2...

    用户1173509
  • 几种js 方法实现倒计时 原

    1、用js  setInterval  实现,每间隔一秒调用一次倒计时函数,在函数里面设置为0 时,取消定时器

    tianyawhl
  • Linux下FTP虚拟账号环境部署总结

    vsftp的用户有三种类型:匿名用户、系统用户、虚拟用户。 1)匿名登录:在登录FTP时使用默认的用户名,一般是ftp或anonymous。 2)本地用户登录:...

    洗尽了浮华
  • Python-数据挖掘-贴吧案例-上

    https://tieba.baidu.com/f? 是基础部分,问号后面的 “kw=爬虫&ie=utf-8&pn=200”是参数部分。参数部分的“爬虫”是搜索...

    小团子
  • iOS UITableView 无数据占位图

    在使用TableView的时候,经常会遇到一些无数据需要用到占位图的情况,所以就写一个控件来实现。 思路:使用UITableView Category来实现,...

    赵哥窟

扫码关注云+社区

领取腾讯云代金券