DOMContentLoaded VS onload VS onreadystatechange

1. DOMContentLoaded 在页面html、script、style加载完毕即可触发,无需等待所有资源(image/iframe)加载完毕。(IE9+)

2. onload是最早支持的事件,要求所有资源加载完毕触发。

3. onreadystatechange 开始在IE引入,后来其它浏览器也有一定的实现。涉及以下 document , applet, embed, frame, frameset, iframe, img, input:image, link, script, xml
标签的元素,都触发该事件。通常来讲,会有 loading /interactive/complete几个状态值。
对于页面加载完毕,检测的是 document.readystate === "complete" 状态。就目前IE6~8的测试结果来看,这个事件的触发约 等同于 onload 事件, 触发顺序上onload在后面。

其它需要注意的是:
1. IE11+,对于script标签,onreadystatechange不再受支持,请用onload来判断js的加载完成。
(查看;https://msdn.microsoft.com/en-us/library/ms536957(v=vs.85).aspx)



2. 在IE中,document.readystate === "interactive" ,在图片、js加载完成之前就已经触发,所以不能用来模拟 DOMContentLoaded 事件。
	// 模拟DOMContentLoaded ------- 不要这样用,这是错误的。
	document.onreadystatechange = function () {
	  if (document.readyState == "interactive") {
	    initApplication();
	  }
	}

(示例代码源自:https://developer.mozilla.org/zh-CN/docs/Web/API/Document/readyState 。)


3. 如果你在onload的事件函数里面,再次监听 onload事件,那么,是不会再次触发函数的。
	function addOnload(callback) {
	    if ( "undefined" != typeof(window.attachEvent) ) {
	        return window.attachEvent("onload", callback);
	    }
	    else if ( window.addEventListener ){
	        return window.addEventListener("load", callback, false);
	    }
	}

	function onload1() {
	    document.getElementById('results').innerHTML += "First onload executed.";
	    
		//没用的,onload2是不会被调用的.
	    addOnload(onload2);
	}

	function onload2() {
	    document.getElementById('results').innerHTML += "Second onload executed.";
	}

	addOnload(onload1);

(查看:http://www.stevesouders.com/blog/2014/09/12/onload-in-onload/)
因此,对于异步加载的JS,为了保证js能在onload里面触发,可以先判断 document.readystate === "complete",如果成功,则立即执行函数。

4. 最后,看看jQuery1.8里面,有关 ready 函数的实现:

 // The ready event handler and self cleanup method
    DOMContentLoaded = function() {
        if ( document.addEventListener ) {
            document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
            jQuery.ready();
        } else if ( document.readyState === "complete" ) {
            // we're here because readyState === "complete" in oldIE
            // which is good enough for us to call the dom ready!
            document.detachEvent( "onreadystatechange", DOMContentLoaded );
            jQuery.ready();
        }
    },

////////////////////////////////////////////////

jQuery.ready.promise = function( obj ) {
    if ( !readyList ) {

        readyList = jQuery.Deferred();

        // Catch cases where $(document).ready() is called after the
        // browser event has already occurred.
        if ( document.readyState === "complete" || ( document.readyState !== "loading" && document.addEventListener ) ) {
            // Handle it asynchronously to allow scripts the opportunity to delay ready
            setTimeout( jQuery.ready, 1 );

        // Standards-based browsers support DOMContentLoaded
        } else if ( document.addEventListener ) {
            // Use the handy event callback
            document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );

            // A fallback to window.onload, that will always work
            window.addEventListener( "load", jQuery.ready, false );

        // If IE event model is used
        } else {
            // Ensure firing before onload, maybe late but safe also for iframes
            document.attachEvent( "onreadystatechange", DOMContentLoaded );

            // A fallback to window.onload, that will always work
            window.attachEvent( "onload", jQuery.ready );

            // If IE and not a frame
            // continually check to see if the document is ready
            var top = false;

            try {
                top = window.frameElement == null && document.documentElement;
            } catch(e) {}

            if ( top && top.doScroll ) {
                (function doScrollCheck() {
                    if ( !jQuery.isReady ) {

                        try {
                            // Use the trick by Diego Perini
                            // http://javascript.nwbox.com/IEContentLoaded/
                            top.doScroll("left");
                        } catch(e) {
                            return setTimeout( doScrollCheck, 50 );
                        }

                        // and execute any waiting functions
                        jQuery.ready();
                    }
                })();
            }
        }
    }
    return readyList.promise( obj );
};




https://msdn.microsoft.com/en-us/library/ms536957(v=vs.85).aspx
https://github.com/dperini/ContentLoaded/blob/master/src/contentloaded.js
https://developer.mozilla.org/zh-CN/docs/Web/API/Document/readyState
http://www.stevesouders.com/blog/2014/09/12/onload-in-onload/

你可能感兴趣的:(jquery,js)