jQuery文档初始化函数原理

来源:互联网 发布:unity3d内景 编辑:程序博客网 时间:2024/06/11 01:02

在jQuery的脚本使用中,经常注册文档初始化函数,比如:$(function(){}); 那么这句话原理是什么呢?

原理一、把completed函数注册到文档加载的原生事件中

关键在这一句document.addEventListener("DOMContentLoaded", completed, false);

jQuery.ready.promise = function (obj) {        if (!readyList) {            // 如果没有,新建一个 Deferred 对象            // Deferred 用于处理异步延时回调函数,也就是内部用于 ready 的一个异步队列            readyList = jQuery.Deferred();            // Catch cases where $(document).ready() is called after the browser event has already occurred.            // we once tried to use readyState "interactive" here, but it caused issues like the one            // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15            if (document.readyState === "complete") {                // Handle it asynchronously to allow scripts the opportunity to delay ready                // setTimeout : 在setTimeout中触发的函数, 一定会在DOM准备完毕后触发.(即是 DOMContentLoaded)                setTimeout(jQuery.ready);                // Standards-based browsers support DOMContentLoaded                // 支持 DOMContentLoaded 的浏览器 (除去ie 6 7 8)            } else if (document.addEventListener) {                // Use the handy event callback                // 当检测的 document.readyState 的值不为 complete 时, 用 readystatechange 监听 document.readyState 值的变化事件                document.addEventListener("DOMContentLoaded", completed, false);                // A fallback to window.onload, that will always work                // 一种退而求其次的方法,确保一定会发生                window.addEventListener("load", completed, false);                // If IE event model is used                // 如果是 IE 浏览器(6、7、8)            } else {                // Ensure firing before onload, maybe late but safe also for iframes                document.attachEvent("onreadystatechange", completed);                // A fallback to window.onload, that will always work                window.attachEvent("onload", completed);                // If IE and not a frame                // continually check to see if the document is ready                // 如果是 IE 且不是在 frame 中                var top = false;                try {                    top = window.frameElement == null && document.documentElement;                } catch (e) { }                // 如果是IE并且不是iframe                if (top && top.doScroll) {                    // 这里有个立即执行函数 doScrollCheck()                    (function doScrollCheck() {                        if (!jQuery.isReady) {                            try {                                // Use the trick by Diego Perini                                // http://javascript.nwbox.com/IEContentLoaded/                                // Diego Perini 在 2007 年的时候,报告了一种检测 IE 是否加载完成的方式,使用 doScroll 方法调用                                // 原理就是对于 IE 在非 iframe 内时,只有不断地通过能否执行 doScroll 判断 DOM 是否加载完毕                                // 在上述中间隔 50 毫秒尝试去执行 doScroll,注意,由于页面没有加载完成的时候,调用 doScroll 会导致异常,所以使用了 try - catch 来捕获异常                                // 直到DOM渲染结束了,这个时候 doScroll 方法不会抛出异常,然后就调用$.ready()                                top.doScroll("left");                            } catch (e) {                                return setTimeout(doScrollCheck, 50);                            }                            // detach all dom ready events                            detach();                            // and execute any waiting functions                            jQuery.ready();                        }                    })();                }            }        }        // 函数返回的是deferred对象,这就可以加上链式操作了        // 可以使用 .done .fail 等方法        return readyList.promise(obj);        // Populate the class2type map    };


原理二、使用deferred对象管理队列方法

还是上面的代码,,注意到有这么一句:readyList = jQuery.Deferred();,这个readyList是闭包内的“全局变量”,在completed调用栈中也会使用到

原理三、completed函数触发后会触发readList的resolveWith方法进行触发

关键代码:readyList.resolveWith(document,[jQuery])进行触发deferred函数队列




/*注册文档就绪函数:$(function(){});*//*首先下面几种写法都是一样的,最终都是jQuery(document).ready(function(){});$("#box").ready(function(){});$(function(){});jQuery(document).ready(fn);-->jQuery.ready.promise().done(fn);-->在promise方法中初始化readyList这是一个deferred对象添加dom加载完成事件"completed"-->执行readList.promise()的done方法注册dom加载完成方法当文档加载完成后触发了complete方法,这个方法中执行如下:-->移除dom加载事件中注册的complete方法-->执行jQuery.ready()方法-->调用readyList.resolveWith(document,[jQuery])进行触发deferred函数队列*/


0 0
原创粉丝点击