javascript 模擬JQuery的Ready方法實(shí)現(xiàn)并出現(xiàn)的問題
更新時(shí)間:2009年12月06日 00:55:13 作者:
今天在閱讀網(wǎng)上一些模擬Jq的ready方法時(shí),發(fā)現(xiàn)一些小細(xì)節(jié),就是網(wǎng)上的ready事件大部分都是在onload事件執(zhí)行后加載,而jquery確能在onload加載前。
dom加載完后執(zhí)行,一直不了解,基于對(duì)網(wǎng)上的一些方法邏輯不了解,所以去看了《jquery源代碼研究(ready函數(shù)) 》這篇文章后自己寫入如下代碼(已有詳細(xì)說明)
<!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; //是否已經(jīng)加載完畢
var readBound=false; //判斷是否已經(jīng)調(diào)用過循環(huán)事件
var readylist=[]; //把需要執(zhí)行的方法先暫存在這個(gè)數(shù)組里
//判斷瀏覽器,該方法來自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方法只執(zhí)行一遍
return;
}
readBound=true;
//For IE并且不是嵌套在frame中
if (Browser.msie && window==top)
{
(function(){
if (isReady) {
return;
}
try {
document.documentElement.doScroll("left"); //如果沒加載dom完畢這個(gè)會(huì)報(bào)錯(cuò)
}
catch (error) {
setTimeout(arguments.callee, 0); //循環(huán)調(diào)用父函數(shù),也就是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); //加載完畢,直接調(diào)用
}else{
readylist.push(fn);//如果還沒加載完成則將該方法暫存到readylist數(shù)組中,以便以后調(diào)用
}
return this;
}
};
//靜態(tài)方法:加載完畢執(zhí)行
Test.Done=function(){
if (!isReady) {
isReady=true;
}
readylist[0].call(document);
}
Darren=Test;
})();
//測(cè)試
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做對(duì)比,所以測(cè)試時(shí)候需要導(dǎo)入jq庫。函數(shù)本身是沒有調(diào)用jq的,請(qǐng)放心引用。
代碼我通過封裝完成,直接Darren.ready(fn)就可執(zhí)行。
后來通過測(cè)試還是出現(xiàn)一個(gè)奇怪的問題:在FF下的執(zhí)行順序是jq -> my -> load 。也就是說我這個(gè)函數(shù)能夠在onload事件執(zhí)行前觸發(fā),但會(huì)晚于jq的ready。對(duì)這個(gè)還是比較滿意。
但是在IE下測(cè)試居然是:jq -> load -> my。也就是 我的這個(gè)函數(shù)雖然能夠把代碼提前,但是還是在onload事件執(zhí)行后觸發(fā)的,百思不得其解。
完同志們解答下如何實(shí)現(xiàn)onload之前執(zhí)行,jq又是怎么實(shí)現(xiàn)的,我完全模擬jq的結(jié)構(gòu),但是還是不能達(dá)到目的,難道中間有漏?
另大家可以參考下面的代碼
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();
}
});
}
}
}
復(fù)制代碼 代碼如下:
<!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; //是否已經(jīng)加載完畢
var readBound=false; //判斷是否已經(jīng)調(diào)用過循環(huán)事件
var readylist=[]; //把需要執(zhí)行的方法先暫存在這個(gè)數(shù)組里
//判斷瀏覽器,該方法來自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方法只執(zhí)行一遍
return;
}
readBound=true;
//For IE并且不是嵌套在frame中
if (Browser.msie && window==top)
{
(function(){
if (isReady) {
return;
}
try {
document.documentElement.doScroll("left"); //如果沒加載dom完畢這個(gè)會(huì)報(bào)錯(cuò)
}
catch (error) {
setTimeout(arguments.callee, 0); //循環(huán)調(diào)用父函數(shù),也就是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); //加載完畢,直接調(diào)用
}else{
readylist.push(fn);//如果還沒加載完成則將該方法暫存到readylist數(shù)組中,以便以后調(diào)用
}
return this;
}
};
//靜態(tài)方法:加載完畢執(zhí)行
Test.Done=function(){
if (!isReady) {
isReady=true;
}
readylist[0].call(document);
}
Darren=Test;
})();
//測(cè)試
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做對(duì)比,所以測(cè)試時(shí)候需要導(dǎo)入jq庫。函數(shù)本身是沒有調(diào)用jq的,請(qǐng)放心引用。
代碼我通過封裝完成,直接Darren.ready(fn)就可執(zhí)行。
后來通過測(cè)試還是出現(xiàn)一個(gè)奇怪的問題:在FF下的執(zhí)行順序是jq -> my -> load 。也就是說我這個(gè)函數(shù)能夠在onload事件執(zhí)行前觸發(fā),但會(huì)晚于jq的ready。對(duì)這個(gè)還是比較滿意。
但是在IE下測(cè)試居然是:jq -> load -> my。也就是 我的這個(gè)函數(shù)雖然能夠把代碼提前,但是還是在onload事件執(zhí)行后觸發(fā)的,百思不得其解。
完同志們解答下如何實(shí)現(xiàn)onload之前執(zhí)行,jq又是怎么實(shí)現(xiàn)的,我完全模擬jq的結(jié)構(gòu),但是還是不能達(dá)到目的,難道中間有漏?
另大家可以參考下面的代碼
復(fù)制代碼 代碼如下:
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實(shí)現(xiàn)jquery的document.ready功能的實(shí)現(xiàn)代碼
- JQuery的ready函數(shù)與JS的onload的區(qū)別詳解
- 模擬jQuery中的ready方法及實(shí)現(xiàn)按需加載css,js實(shí)例代碼
- JQuery的read函數(shù)與js的onload不同方式實(shí)現(xiàn)
- jQuery中的read和JavaScript中的onload函數(shù)的區(qū)別
- JavaScript的jQuery庫中ready方法的學(xué)習(xí)教程
- 全面解析jQuery $(document).ready()和JavaScript onload事件
- jquery $(document).ready() 與window.onload的區(qū)別
- jQuery之$(document).ready()使用介紹
- jQuery的Read()方法代替原生JS詳解
相關(guān)文章
詳解javascript appendChild()的完整功能
這篇文章主要介紹了詳解javascript appendChild()的完整功能,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-08-08詳解JavaScript實(shí)現(xiàn)動(dòng)態(tài)的輪播圖效果
這篇文章主要介紹了JavaScript實(shí)現(xiàn)動(dòng)態(tài)的輪播圖效果,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04用document.documentElement取代document.body的原因分析
ll建議用document.documentElement代替document.body2009-11-11bootstrap時(shí)間插件daterangepicker使用詳解
這篇文章主要為大家詳細(xì)介紹了bootstrap時(shí)間插件daterangepicker使用,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10javascript實(shí)現(xiàn)添加附件功能的方法
這篇文章主要介紹了javascript實(shí)現(xiàn)添加附件功能的方法,在我們編輯信息時(shí),有時(shí)候需要附加文件、圖片實(shí)現(xiàn)上傳功能,通過本文了解javascript是如何實(shí)現(xiàn)附加功能的,請(qǐng)閱讀。2015-11-11JavaScript面向?qū)ο笾w會(huì)[總結(jié)]
看過很多JavaScript書,對(duì)JavaScript的面向?qū)ο笾v的都比較深入,但是并沒有做到深入淺出,總結(jié)了我做的一些JavaScript程序的經(jīng)驗(yàn),以簡潔明了的文字使大家明白JavaScript面向?qū)ο蟮膶?shí)現(xiàn)。2008-11-11