您好,欢迎来到码863代码分享网! 请[登录] / [注册]

模拟JQuery的Ready方法实现并出现的问题

编辑

今天在阅读网上一些模拟Jq的ready方法时,发现一些小细节,就是网上的ready事件大部分都是在onload事件执行后加载,而jquery确能在onload加载前,dom加载完后执行,一直不了解,基于对网上的一些方法逻辑不了解,所以去看了《jquery源代码研究(ready函数) 》这篇文章后自己写入如下代码(已有详细说明):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>document.ready</title>
<script type="text/javascript" src="js/jquery-1.3.2.js"></script>
<script type="text/javascript">
    var Darren;
    (function(){
        var isReady=false;    //是否已经加载完毕
        var readBound=false;    //判断是否已经调用过循环事件
        var readylist=[];    //把需要执行的方法先暂存在这个数组里
    
        //判断浏览器,该方法来自Cloudgamer JavaScript Library v0.1
        var Browser = (function(ua){
            var b = {
                msie: /msie/.test(ua) && !/opera/.test(ua),
                opera: /opera/.test(ua),
                safari: /webkit/.test(ua) && !/chrome/.test(ua),
                firefox: /firefox/.test(ua),
                chrome: /chrome/.test(ua)
            };
            var vMark = "";
            for (var i in b) {
                if (b[i]) {
                    vMark = i;
                }
            }
            if (b.safari) {
                vMark = "version";
            }
            b.version = RegExp("(?:" + vMark + ")[\\/: ]([\\d.]+)").test(ua) ? RegExp.$1 : "0";
            
            b.ie = b.msie;
            b.ie6 = b.msie && parseInt(b.version) == 6;
            b.ie7 = b.msie && parseInt(b.version) == 7;
            b.ie8 = b.msie && parseInt(b.version) == 8;
            
            return b;
        })(window.navigator.userAgent.toLowerCase());
        
        function bindReady()
        {
            if(readBound){    //保证bindReady方法只执行一遍
                return;
            }
            readBound=true;
            
            //For IE并且不是嵌套在frame中
            if (Browser.msie && window==top) 
            {
                (function(){
                    if (isReady) {
                        return;
                    }
                    try {
                        document.documentElement.doScroll("left");    //如果没加载dom完毕这个会报错
                    } 
                    catch (error) {
                        setTimeout(arguments.callee, 0);    //循环调用父函数,也就是ready方法
                        return;
                    }
                    Test.Done();
                })();
            }else if(Browser.firefox)//For FF        
            {        
                document.addEventListener( "DOMContentLoaded", Test.Done, false );
            }
        }
        var Test={
            ready:function(fn){
                bindReady();//判断是否加载完毕
                if(isReady)
                {
                    fn.call(document);    //加载完毕,直接调用
                }else{
                    readylist.push(fn);//如果还没加载完成则将该方法暂存到readylist数组中,以便以后调用
                }
                return this;
            }        
        };
        //静态方法:加载完毕执行
        Test.Done=function(){
            if (!isReady) {
                isReady=true;
            }        
            readylist[0].call(document);
        }
        Darren=Test;
    })();
    
    
    //测试
    Darren.ready(function(){
        alert("my");
        document.getElementById("test").innerHTML="haha"    //成功读取dom
    });
    $(function(){alert("jq")});
    window.onload=function(){alert("default")}
</script>
</head>
<body>
<div id="test">test</div>
</body>
</html>

由于要和jq做对比,所以测试时候需要导入jq库。函数本身是没有调用jq的,请放心引用。

代码我通过封装完成,直接Darren.ready(fn)就可执行。

后来通过测试还是出现一个奇怪的问题:在FF下的执行顺序是jq -> my -> load 。也就是说我这个函数能够在onload事件执行前触发,但会晚于jq的ready。对这个还是比较满意。

但是在IE下测试居然是:jq -> load -> my。也就是 我的这个函数虽然能够把代码提前,但是还是在onload事件执行后触发的,百思不得其解。

完同志们解答下如何实现onload之前执行,jq又是怎么实现的,我完全模拟jq的结构,但是还是不能达到目的,难道中间有漏?

作者:Darren


CopyRight 2002~2023 精通2100网 联系邮箱:qqtxt@163.com
版权所有:精通2100网 湘ICP备2023018646号-1
MYSQl共执行 3 个查询,用时 0.0017929077148438 秒,PHP脚本用时 0.004180 秒,占用内存 0.551 MB,Gzip 已启用