domReady的兼容性实现方法

一、为何要实现domReay方法?

举例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>domready</title>
    <script src="domready.js"></script>
    <script>
          document.getElementById('p01').style.color='#ff0000'; //抛出错误 TypeError: document.getElementById(...) is null
    </script>
</head>
<body>
    <p id="p01">javascript中domready的实现方法</p>
</body>
</html>

我们需要给一些元素的事件绑定处理函数。但问题是,如果那个元素还没有加载到页面上,但是绑定事件已经执行完了,是没有效果的,如上所示。

平时我们都是如此做:

  <script>
    window.onload=function(){        
        document.getElementById('p01').style.color='#ff0000';
    }
  </script>

onload 事件触发时,需要等待页面上所有的DOM,样式表,脚本,图片,flash都已经加载完成。

DOMContentLoaded 事件触发时,仅当DOM加载完成,不包括样式表,图片,flash。

这两个事件大致就是用来避免这样一种情况,将绑定的函数放在这两个事件的回调中,保证能在页面的某些元素加载完毕之后再绑定事件的函数。

当然DOMContentLoaded机制更加合理,因为我们可以容忍图片,flash延迟加载,却不可以容忍看见内容后页面不可交互。

二、domReady实现

function domReady(fn){
    //现代浏览器支持方法
    if(document.addEventListener){
        document.addEventListener('DOMContentLoaded', fn , false);
    }else {
        IEContentLoaded(fn);
    }

    //IE下模拟DOMContentLoaded
    function IEContentLoaded(fn){
        var d = window.document;
        var flag = false;

        //只执行一次用户的回调函数init()
        var init = function () {
            if(!flag){
                flag = true;
                fn();
            }
        };

        //自执行匿名函数
        (function () {
             try {
                 // DOM树未创建之前调用doScroll会抛出错误
                  d.documentElement.doScroll('left');
              } catch(e) {
                  // 延迟再执行一次
                  setTimeout(arguments.callee, 50);
                  return;
              }
              //没有错误就表示DOM树创建完毕,然后立即执行用户回调
              init();
        })();

        //监听document的加载状态
        d.onreadystatechange = function () {
            //如果是在domready之后绑定的函数,就立马执行
            if(d.readyState == 'complete'){
                d.onreadystatechange = null;
                init();
            }
        }

    }
}

HTML代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>domready</title>
    <script src="domready.js"></script>
    <script>
        domReady(function () {
             document.getElementById('p01').style.color='#ff0000';
        })
    </script>
</head>
<body>
    <p id="p01">javascript中domready的实现方法</p>
</body>
</html>