• jQuery源码学习9——DOMReady加载


    先将和ready相关的代码都归纳出来

        function jQuery(a,c) {
            if ( a && a.constructor == Function && jQuery.fn.ready ){
                return jQuery(document).ready(a);
            }
        }
        jQuery.fn.extend({
            ready: function(f) {
                if ( jQuery.isReady )
                    f.apply( document );
                else {
                    jQuery.readyList.push( f );
                }        
                return this;
            }
        });
        jQuery.extend({
            isReady: false,
            readyList: [],
            ready: function() {
                if ( !jQuery.isReady ) {
                    jQuery.isReady = true;
                    if ( jQuery.readyList ) {
                        for ( var i = 0; i < jQuery.readyList.length; i++ )
                            jQuery.readyList[i].apply( document );
                        jQuery.readyList = null;
                    }
                }
            }
        });
        new function(){
            if ( jQuery.browser.mozilla || jQuery.browser.opera ) {
                document.addEventListener( "DOMContentLoaded", jQuery.ready, false );
            } else if ( jQuery.browser.msie ) {
                document.write("<scr" + "ipt id=__ie_init defer=true " + 
                    "src=//:></script>");
                var script = document.getElementById("__ie_init");
                script.onreadystatechange = function() {
                    if ( this.readyState == "complete" )
                        jQuery.ready();
                };
                script = null;
            } else if ( jQuery.browser.safari ) {
                jQuery.safariTimer = setInterval(function(){
                    if ( document.readyState == "loaded" || 
                        document.readyState == "complete" ) {
                        clearInterval( jQuery.safariTimer );
                        jQuery.safariTimer = null;
                        jQuery.ready();
                    }
                }, 10);
            } 
            jQuery.event.add( window, "load", jQuery.ready );    
        }

    jQuery里面的初始化已经在document或者script上绑定了一些事件

    FF和opera下,document的DOMContentLoaded完成之后触发jQuery.ready事件

    IE下,script的onreadystatechange事件中script.readyState是complete的时候触发jQuery.ready事件

    webkit内核下貌似是手动实现了一个onreadystatechange事件,开了一个定时器,每隔10ms监听一下document上的readyState是否为complete

    如果是complete的话,触发jQuery.ready事件,顺便把这个定时器干掉

    最后做了一个万全的方案,window对象的onload方法触发时,也就是页面中所有东西都加载完的时候触发jQuery.ready事件

    通过上述分析可以发现不管在哪个浏览器下都有两次机会触发jQuery.ready事件

    第一次就是在DOM结构加载完毕(DOMContentLoaded完毕或者readyState为complete)

    第二次就是在页面所有资源加载完毕(window.onload)

    这两次触发jQuery.ready是相互竞争的

    如果不做任何处理,一定会重复两次去执行jQuery.ready

    所以jQuery初始化的时候加了一个isReady的一个静态方法

    初始值为false

    在触发jQuery.ready的时候,先if判断了一下jQuery.ready的值

    如果jQuery.ready的值是false的话,证明之前没有触发过jQuery.ready

    jQuery.ready里面马上把jQuery.isReady变成true,代表触发过了

    那第二次再触发jQuery.ready的时候里面再判断jQuery.isReady

    变成了true的话就什么都不做了

    我们关键看jQuery.ready是false,即之前没有触发过的情况

    在这种情况下进一步判断jQuery.readyList

    jQuery.readyList也是在jQuery初始化的时候定义的

    初始值是一个空数组

    我们在以$(function(){})或者$(document).ready(function(){})调用的时候都会在某个时机把里面的函数添加到jQuery.readyList中

    数组不管空还是不空都是真,所以这个判断始终为真

    进入if判断之后就循环jQuery.readyList里面的所有函数

    依次执行每个函数

    或许是考虑到jQuery.readyList在执行完以后就没什么用了,所以就把readyList直接赋值为null了

    我们通过$(function(){})或者$(document).ready(function(){})的调用方式希望页面加载完毕触发里面的函数时

    会调用jQuery.fn.ready这个方法

    这个jQuery.fn.ready里面的实现虽然只有短短几行代码,但很值得分析一下

    里面通过判断jQuery.isReady的值来执行不同的操作

    前面分析到jQuery.isReady初始化为false

    而且是在DOMContentLoaded/readyState=="complete"/onload任何一种完事了之后变成true的

    在jQuery.fn.ready里面

    jQuery.isReady是false的时候我们是把事件function添加到readyList队列里面

    jQuery.isReady是true的时候我们直接执行了function

    这里就不得不佩服jQuery作者英明的思路了

    isReady是false的时候放在队列里面的方法在DOMContentLoaded/readyState=="complete"/onload完毕之后在jQuery.ready()中去挨个执行

    isReady是true的时候,页面已经加载完毕,所以就直接执行function了

    还是用例子说更直观一些,例如下面的代码

        $(aaa);
        $(bbb);
        $(ccc);
        $(ddd);
        function aaa(){
            alert(1);
        }
        function bbb(){
            alert(2);
        }
        function ccc(){
            alert(3);
        }
        function ddd(){
            $(eee);
        }
        function eee(){
            alert(4);
        }

    最开始我们引入的jQuery执行的时候其实已经绑定了DOMContentLoaded/readyState=="complete"/onload这一系列事件

    那从引入的jQuery文件执行完毕到这些事件触发并执行jQuery.ready之前js会接着往下执行$(aaa) $(bbb) $(ccc)...

    假如执行到$(bbb)的时候

    DOMContentLoaded/readyState=="complete"/onload里面中的一个触发了

    那在jQuery.ready执行的时候jQuery.readyList里面就会有aaa bbb两个函数

    为什么是这两个呢?

    因为在DOMContentLoaded/readyState=="complete"/onload触发之前,每执行一次$(xxx)

    判断之后发现jQuery.isReady是false,就会将aaa bbb这两个函数push到readyList中了

    此后jQuery.isReady的值就是true了

    再执行$(ccc) $(ddd)的话,判断之后发现jQuery.isReady是true

    ccc和ddd就会直接执行

    执行ddd的时候发现ddd里面又执行了$(eee)

    同样jQuery.isReady仍然是true,所以还是会直接执行eee

  • 相关阅读:
    qt install (1)
    learning rewind func
    learning strrchr func
    learning memchr func
    git lfs setpu(4)
    大端与小端
    git branch/meger step(3)
    git log/show/HEAD step(2)
    调用外部EXE文件
    获取计算机上的所有进程
  • 原文地址:https://www.cnblogs.com/zhaohuiziwo901/p/4994104.html
Copyright © 2020-2023  润新知