好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

onhashchange事件

onhashchange事件

onhashchange事件是针对AJAX无缝刷新导致后退键失效而产生的事件,因此属于一个够新的事件,浏览器兼容性如下:

Feature Chrome Firefox IE Opera Safari support 5.0 3.6 (1.9.2) 8.0 10.6 5.0

由于chrome引发的版本号竞赛,现在chrome20+,firefox16+,opera12了,因此对于标准浏览器我们不必顾虑支持问题,精力集中在IE678上。IE8在兼容模式下虽然有此事件,但不生效。这个检测也很简单。至于如何产生历史,这也很简单,直接在隐藏iframe中调用document.write方法就行。hash的变化,是通过定时器检测,不十分及时,但对于坚持IE67的操蛋用户就不应该给好脸色他们看!

如何观察hash的变化呢?这其实有三个hash值,一个是主窗口之前的hash值(last_hash),主窗口当前的hash值,一个是iframe中的hash值(history_hash),我们可以比较前两者得知hashchange,但当用户点击后退按钮后,AJAX引发的效果是作用于iframe中的,因此这时是比较last_hash与history_hash。发生变化后,我们再手动修改主窗口的hash,触发onhashchange回调。

最后提一提hash值的提取,这里存在两个兼容性问题:

IE6直接用location.hash取hash,可能会取少一部分内容:

比如 http://www.cnblogs.com/rubylouvre#stream/xxxxx?lang=zh_c

ie6 => location.hash = #stream/xxxxx

其他浏览器 => location.hash = #stream/xxxxx?lang=zh_c

firefox 会自作多情对hash进行decodeURIComponent

比如 http://www.cnblogs.com/rubylouvre/#!/home/q={%22thedate%22:%2220121010~20121010%22}

firefox 15 => #!/home/q={"thedate":"20121010~20121010"}

其他浏览器 => #!/home/q={%22thedate%22:%2220121010~20121010%22}

下面是mass Framework中的实现

define( "hashchange" , [ "$event" ], function (){

     $.log( "已加载hashchange模块 by 司徒正美" )

 

     var   hashchange = 'hashchange' ,  DOC = document,  documentMode = DOC.documentMode,

     supportHashChange = ( 'on'   + hashchange in   window) && ( documentMode === void 0 || documentMode > 7 );

     

     $.fn[ hashchange ] = function (callback){

         return   callback?  this .bind(hashchange, callback ) : this .fire( hashchange);

     }

     $.fn[ hashchange ].delay = 50;

     if (!supportHashChange){

         $.log( "不支持hashchange,使用iframe加定时器模拟" )

         var   iframe, timeoutID, html = '<!doctype html><html><body>#{0}</body></html>'

          

         if ( $.fn[ hashchange ].domain){

             html = html.replace( "<body>" , "<script>document.domain =" +

                 $.fn[ hashchange ].domain + "</script><body>"   )

         }

 

         function   getHash ( url) { //用于取得当前窗口或iframe窗口的hash值

             url = url || DOC.URL

             return   '#'   + url.replace( /^[^#]*#?(.*)$/, '$1'   );

         }

         function   getHistory(){

             return   getHash(iframe.location);

         }

         function   setHistory(hash, history_hash){

             var   doc = iframe.document;

             if   (  hash !== history_hash ) { //只有当新hash不等于iframe中的hash才重写

                 //用于产生历史

                     doc.open();

                     doc.write($.format(html, hash));

                     doc.close();

             }

         }

         var   last_hash = getHash(), history_hash, hash = "#" ;

         $.eventAdapter[ hashchange ] = {

             setup: function (desc) {

                 $.require( "ready" , function (){

                     if   (!iframe) {

                         //创建一个隐藏的iframe,使用这博文提供的技术 http://www.paciellogroup.com/blog/?p=604.

                         //iframe是直接加载父页面,为了防止死循环,在DOM树未建完之前就擦入新的内容

                         var   el = $( '<iframe tabindex="-1" style="display:none" widht=0 height=0 title="empty" />' ).appendTo( document.body )[0], fn

                         iframe = el.contentWindow

                         $.bind(el, "load" ,fn = function (){

                             $.unbind(el, "load" , fn)

                             var   doc = iframe.document

                             doc.open();

                             doc.write($.format(html, hash))

                             doc.close();

                             timeoutID = setInterval(poll,  $.fn[ hashchange ].delay)

                         });

                         function   poll() {

                             var   hash = getHash(), //取得主窗口中的hash

                             history_hash = iframe.document.body.innerText; //取得现在iframe中的hash

                             if (hash !== last_hash){ //如果是主窗口的hash发生变化

                                 setHistory(last_hash = hash, history_hash )

                                 $(desc.currentTarget).fire(hashchange)

                             } else   if (history_hash !== last_hash){ //如果按下回退键,

                                 location.href = location.href.replace( / #.*/, '' ) + history_hash;

                             }

                         }

                     }

                     

                 });

             },

             teardown: function (){

                 if (!iframe){

                     clearTimeout(timeoutID);

                     $(iframe).remove();

                     iframe = 0;

                 }

             }

         };

     }

 

})

具体例子可见 这里

打开后点击“运行代码”,然后点击页面触发hashchange,它的回调会在页面添加一行红字,然后再点击后退按钮就看到效果了。

 

 

标签:  javascript ,  mass

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于onhashchange事件的详细内容...

  阅读:57次