今天在阅读网上一些模拟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的结构,但是还是不能达到目的,难道中间有漏?

posted on 2009-12-04 17:32  wbkt2t  阅读(2586)  评论(3编辑  收藏  举报