DOMContentLoaded实现

IE系列直到IE9才支持DOMContentLoaded事件,对于IE8及其之前版本,如果html内没有框架,则可以采用document.documentELement.doScroll来判断

是否构建好DOM树;如果html内有框架,则利用document的onreadystatechange事件判断当前DOM树是否构建完毕(框架html内容(只是html文件)加载之后DOM树构建完毕)。

所以可以采用这种方式:

  

        /**
         * 实现DomContentLoaded的兼容性
         * @param callback
         */
        var onDomContentLoaded = function(callback){
            var onlyOnce = true;
            var onReady = function(callback){
                if(onlyOnce){
                    onlyOnce = false;
                    onDomContentLoaded.isDomReady = true;
                    try{
                        callback();
                    }catch(e){
                        throw(new Error('DOM Ready callback occurs an error!'))
                    }
                }
                return;
            }

            if(S.browser.isIe && !('HTMLElement' in window)){  // lt IE9
                if(self.top === self){
                    function s(){
                        try{
                            document.documentElement.doScroll('left');
                            onReady(callback);
                            return;
                        }catch(e){
                            setTimeout(s,50);
                        }
                    }
                    s();
                }else{ //包含框架
                    document.attachEvent('onreadystatechange',function(){
                        if(document.readyState === 'complete'){
                            onReady(callback);
                            document.detachEvent('onreadystatechange',arguments.callee);
                        }
                    });
                }

                document.onload = function(){
                    onReady(callback);
                    document.onload = null;
                };
            }else{
                document.addEventListener('DOMContentLoaded',function(){
                    onReady(callback);
                    document.removeEventListener('DOMContentLoaded',arguments.callee);
                },false);

                document.onload = function(){
                    onReady(callback);
                    document.onload = null;
                };
            }
        };    

另外,John Resig也在《精通javascript》提出了一种方法来判断DOM是否构建完毕,那就是不断轮训判断

if(document && document.getElementById && document.getElementsByTagName && document.body)是否为true,若为true,则

DOM构建完毕。

最后,给出David Flanagan所给出的whenReady函数,很有技巧性:

  

/*
 * Pass a function to whenReady() and it will be invoked (as a method of the
 * document) when the document is parsed and ready for manipulation. Registered
 * functions are triggered by the first DOMContentLoaded, readystatechange, or
 * load event that occurs. Once the document is ready and all functions have
 * been invoked, any functions passed to whenReady() will be invoked 
 * immediately.
 */
var whenReady = (function() { // This function returns the whenReady() function
    var funcs = [];    // The functions to run when we get an event
    var ready = false; // Switches to true when the handler is triggered

    // The event handler invoked when the document becomes ready
    function handler(e) {
        // If we've already run once, just return
        if (ready) return;

        // If this was a readystatechange event where the state changed to
        // something other than "complete", then we're not ready yet
        if (e.type === "readystatechange" && document.readyState !== "complete")
            return;
        
        // Run all registered functions.
        // Note that we look up funcs.length each time, in case calling
        // one of these functions causes more functions to be registered.
        for(var i = 0; i < funcs.length; i++) 
            funcs[i].call(document);

        // Now set the ready flag to true and forget the functions
        ready = true;
        funcs = null;
    }

    // Register the handler for any event we might receive
    if (document.addEventListener) {
        document.addEventListener("DOMContentLoaded", handler, false);
        document.addEventListener("readystatechange", handler, false);
        window.addEventListener("load", handler, false);
    }
    else if (document.attachEvent) {
        document.attachEvent("onreadystatechange", handler);
        window.attachEvent("onload", handler);
    }

    // Return the whenReady function
    return function whenReady(f) {
        if (ready) f.call(document); // If already ready, just run it
        else funcs.push(f);          // Otherwise, queue it for later.
    }
}());

 

posted @ 2014-12-08 23:15  royalrover  阅读(413)  评论(0编辑  收藏  举报