比windows.onload更早执行的方法

最近在学习jQuery,里面牵涉到页面的加载问题,无意中看到这篇文章,觉得很好,估计以后能够用上,特意转贴于下:

原文地址:http://www.cnblogs.com/rubylouvre/archive/2010/04/15/1712780.html

domReady第三版


新的版本放弃使用document.write()(实际上我们依赖的是script标签的defer触发机制),主要基于如下几个理由:

  1. XHTML不支持document.write
  2. 当页面上的资源非常少时,会晚于window.onload
  3. document.write有时会覆写我们原有的DOM
  4. document.write生成的script不能通过内部函数移除

外国javascript高手Diego Perini于是发掘了doScroll这个方法。在IE下,doScroll方法存在于所有标签。但我搞来搞去,发现光是doScroll也不行,时不时就发现window.onload执行于domReady之前。只有结合onreadystatechange与doScroll这两个方法,我们才能在IE中搞出与标准浏览器相同的结果。因此你在jQuery,Prototype,swfobject,Ext等类库看到它们共同出现。而onreadystatechange其实也有些问题的,具体自己可能google一下,因此2006年左右实现domReady的代码基本依仗于document.write()。嗯,剩下的我就在代码间的注释中说明吧,这样更一目了解。

?
/*
take from dom library version 1.0, inspired by  jQuery
Copyright 2010-2011 (2011.2.27更新)
Dual licensed under the MIT or GPL Version 2 licenses.
author "司徒正美"
*/
     
       var  dom = [];
       //用于判定页面是否加载完毕
       dom.isReady  = false ;
       //用于添加要执行的函数
       dom.ready = function (fn){
         if  ( dom.isReady ) {
           fn()
         } else  {
           dom.push( fn );
         }
       }
       //执行所有在window.onload之前放入的函数
       dom.fireReady = function () {
         if  ( !dom.isReady ) {
           if  ( !document.body ) {
             return  setTimeout( dom.fireReady, 16 );
           }
           dom.isReady = 1;
           if  ( dom.length ) {
             for ( var  i = 0, fn;fn = dom[i];i++)
               fn()
           }
         }
       }
       //开始初始化domReady函数,判定页面的加载情况
       if  ( document.readyState === "complete"  ) {
         dom.fireReady();
       } else  if (-[1,] ){
         document.addEventListener( "DOMContentLoaded" , function () {
           document.removeEventListener( "DOMContentLoaded" ,  arguments.callee , false  );
           dom.fireReady();
         }, false  );
       } else  {
         //当页面包含图片时,onreadystatechange事件会触发在window.onload之后,
         //换言之,它只能正确地执行于页面不包含二进制资源或非常少或者被缓存时
         document.attachEvent( "onreadystatechange" , function () {
           if  ( document.readyState == "complete"  ) {
             document.detachEvent( "onreadystatechange" , arguments.callee );
             dom.fireReady();
           }
         });
         ( function (){
           if  ( dom.isReady ) {
             return ;
           }
           //doScroll存在于所有标签而不管其是否支持滚动条
           //这里如果用document.documentElement.doScroll(),我们需要判定其是否位于顶层document
           var  node = new  Image
           try  {
             node.doScroll();
             node = null //防止IE内存泄漏
           } catch ( e ) {
             //javascrpt最短时钟间隔为16ms,这里取其倍数
             setTimeout( arguments.callee, 64 );
             return ;
           }
           dom.fireReady();
         })();
       }
 
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta content="IE=8" http-equiv="X-UA-Compatible"/>
    <title>domReady by 司徒正美</title>

    <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
    <title>domReady by 司徒正美</title>
   
    <script type="text/javascript">
           var dom = [];
      //用于判定页面是否加载完毕
      dom.isReady  = false;
      //用于添加要执行的函数
      dom.ready = function(fn){
        if ( dom.isReady ) {
          fn()
        } else {
          dom.push( fn );
        }
      }
      //执行所有在window.onload之前放入的函数
      dom.fireReady = function() {
        if ( !dom.isReady ) {
          if ( !document.body ) {
            return setTimeout( dom.fireReady, 16 );
          }
          dom.isReady = 1;
          if ( dom.length ) {
            for(var i = 0, fn;fn = dom[i];i++)
              fn()
          }
        }
      }
      //开始初始化domReady函数,判定页面的加载情况
      if ( document.readyState === "complete" ) {
        dom.fireReady();
      }else if(-[1,] ){
        document.addEventListener( "DOMContentLoaded", function() {
          document.removeEventListener( "DOMContentLoaded",  arguments.callee , false );
          dom.fireReady();
        }, false );
      }else {
        //当页面包含图片时,onreadystatechange事件会触发在window.onload之后,
        //换言之,它只能正确地执行于页面不包含二进制资源或非常少或者被缓存时
        document.attachEvent("onreadystatechange", function() {
          if ( document.readyState == "complete" ) {
            document.detachEvent("onreadystatechange", arguments.callee );
            dom.fireReady();
          }
        });
        (function(){
          if ( dom.isReady ) {
            return;
          }
          //doScroll存在于所有标签而不管其是否支持滚动条
          //这里如果用document.documentElement.doScroll(),我们需要判定其是否位于顶层document
          var node = new Image
          try {
            node.doScroll();
            node = null//防止IE内存泄漏
          } catch( e ) {
            //javascrpt最短时钟间隔为16ms,这里取其倍数
            //http://blog.csdn.net/aimingoo/archive/2006/12/21/1451556.aspx
            setTimeout( arguments.callee, 64 );
            return;
          }
          dom.fireReady();
        })();
      }
      window.onload = function(){
        var p = document.createElement("p")
        p.innerHTML = "window.onload"
        document.body.appendChild(p);
      };
      dom.ready(function(){
        var p = document.createElement("p")
        p.innerHTML = "domReady1"
        document.body.appendChild(p);
      });
      dom.ready(function(){
        var p = document.createElement("p")
        p.innerHTML = "domReady2"
        document.body.appendChild(p);
      });
  
    
    </script>

  </head>
  <body>
    <h1>domReady第三版</h1>
    <p id="p"></p>
    <h1>加载图片</h1>
    <p><img src="http://images.cnblogs.com/cnblogs_com/rubylouvre/199042/o_s011.jpg"></p>

  </body>
</html>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值