javascript 模拟JQuery的Ready方法实现并出现的问题
javascript 模拟JQuery的Ready方法实现并出现的问题
发布时间:2016-12-30 来源:查字典编辑
摘要:dom加载完后执行,一直不了解,基于对网上的一些方法逻辑不了解,所以去看了《jquery源代码研究(ready函数)》这篇文章后自己写入如下...

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=gb2312" />

<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的结构,但是还是不能达到目的,难道中间有漏?

另大家可以参考下面的代码

复制代码 代码如下:

var ready=function(readyCall) {

if(document.addEventListener)

document.addEventListener("DOMContentLoaded",function() {

document.removeEventListener("DOMContentLoaded",arguments.callee,false);

readyCall();

},false);

else if(document.attachEvent) {//for IE

if(document.documentElement.doScroll && window.self==window.top) {

(function() {

try {

document.documentElement.doScroll("left");

}catch(ex) {

setTimeout(arguments.callee,5);

return;

}

readyCall();

})();

}else {//maybe late but also for iframes

document.attachEvent("onreadystatechange",function() {

if(document.readyState==="complete") {

document.detachEvent("onreadystatechange", arguments.callee);

readyCall();

}

});

}

}

}

推荐文章
猜你喜欢
附近的人在看
推荐阅读
拓展阅读
相关阅读
网友关注
最新Javascript教程学习
热门Javascript教程学习
编程开发子分类