比Jquery的document.ready更快的方法

新的版本放弃使用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 "司徒正美" 
http://www.cnblogs.com/rubylouvre/ 
*/
      
      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(); 
        })(); 
      } 

demo:

View Code
 
<!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>

 

原文链接:我的domReady第三版.司徒正美.http://www.cnblogs.com/rubylouvre/archive/2010/04/15/1712780.html

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值