zoukankan      html  css  js  c++  java
  • 不使用定时器实现的onhashchange

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

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

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

    image

    主流的浏览器(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);
     

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

    image

    image

     

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

    测试用的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; 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="https://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>
  • 相关阅读:
    dblink
    linux 查进程、杀进程、起进程
    oracle 资源统计SQL语句
    DIV+CSS+javascript 手动轮播图
    接受同步数据接口
    java String StringBuffer StringBuilder
    SpringMVC Servlet 分页查询接收参数
    WPF 开发
    收集整理的各地精品青年旅舍大全(
    Linux平台Java调用so库JNI使用例子
  • 原文地址:https://www.cnblogs.com/meteoric_cry/p/1933164.html
Copyright © 2011-2022 走看看