가장 일반적으로 사용되는 것은 window의 onload 이벤트로, 이 이벤트의 실제 효과는 페이지 구문 분석/DOM 트리 구축이 완료된 후 트리거되고 그림, 스크립트와 같은 모든 리소스가 다운로드되는 것입니다. , 스타일 시트, 심지어 iframe까지 완성되었습니다. 이는 많은 실제 응용 프로그램에 있어서 약간 "너무 늦었고" 사용자 경험에 영향을 미칩니다. 이 문제를 해결하기 위해 ff에 DOMContentLoaded 메서드가 추가되었습니다. onload와 비교하여 이 메서드는 다른 리소스가 로드될 때까지 기다리지 않고 페이지의 DOM 콘텐츠가 로드된 후에 트리거됩니다. Webkit 엔진도 버전 525(Webkit nightly 1/2008:525)부터 이 이벤트를 도입했으며 Opera에도 이 방법이 포함되어 있습니다. 아직까지는 주류 IE에서는 이를 추가할 의사가 없습니다. IE에서는 사용할 수 없지만 항상 해결책이 있습니다. 다음은 이 이벤트에 대한 여러 주요 주류 프레임워크의 호환성 버전 구현 계획을 비교한 것입니다.
프로토타입
jQeury
Moontools
dojo
yui
ext
1. 프로토타입
구현 코드
이 구현에는 두 가지 주요 문제가 있습니다. 첫째, document.write를 통해 스크립트를 작성하고 defer를 설정하는 방법은 페이지에 iframe이 포함된 경우 트리거되기 전에 iframe의 콘텐츠가 로드될 때까지 기다립니다. 이는 onload와 다릅니다. 두 번째로 Webkit은 525 이상의 버전에서 DOMContentLoaded 메서드를 도입했으므로 이러한 버전에서는 폴링을 구현할 필요가 없으며 최적화할 수 있습니다.
2. jQuery
// IE 이벤트 모델을 사용하는 경우
} else if ( document.attachEvent ) {
// 로드 전 실행을 보장하세요.
// 늦을 수도 있지만 iframe에도 안전합니다.
document.attachEvent("onreadystatechange", function(){
if ( document.readyState === "complete" ) {
document.detachEvent( "onreadystatechange",args.callee ) ;
jQuery.ready();
}
});
// iframe이 아닌 경우
// 문서가 준비되었는지 계속 확인하세요.
document.documentElement .doScroll && typeof window.frameElement === "undefine" ) (function(){
if ( jQuery.isReady ) return;
try {
// IE를 사용하는 경우 Diego Perini의 트릭
// http://javascript.nwbox.com/IEContentLoaded/
document.documentElement.doScroll("left")
} catch( error ) {
setTimeout( 인수 .callee, 0 );
return;
}
// 대기 함수 실행
jQuery.ready()
})(); / 항상 작동하는 window.onload로의 대체
jQuery.event.add( window, "load", jQuery.ready )
구현 아이디어는 다음과 같습니다.
Webkit과 Firefox를 동일하게 취급하며 둘 다 DOMContentLoaded 이벤트를 직접 등록합니다. 그러나 Webkit은 버전 525 이상에서만 도입되었으므로 잠재적인 호환성이 있습니다. 위험.
IE의 경우 먼저 문서의 onreadystatechange 이벤트를 등록하세요. 테스트 후 이 메서드는 실행되기 전에 모든 리소스가 다운로드될 때까지 기다립니다.
이후 IE이고 페이지가 iframe에 없는 것으로 확인되면 호출이 성공하고 DOMContentLoaded가 트리거될 때까지 setTiemout을 통해 documentElement의 doScroll 메서드가 계속 호출됩니다.
jQuery는 http://javascript.nwbox.com/IEContentLoaded/에서 시작된 IE용 새로운 솔루션입니다. 그 원칙은 IE에서는 DOM 구문 분석이 완료된 후에만 DOM의 일부 메소드를 호출할 수 있다는 것입니다. 프로토타입과 동일합니다. document.write와 비교하면 이 솔루션은 페이지에 iframe이 있을 때 발생하는 오류 문제를 해결할 수 있습니다. 또한 jQuery는 페이지가 iframe에 있을 때 이 메서드가 실패할 것을 걱정하는 것 같아서 구현 코드에서 판단을 내립니다. iframe에 있으면 문서의 onreadystatechange를 통해 구현됩니다. doScroll을 통해 구현됩니다. 그러나 테스트 후에도 doScroll은 iframe에서도 여전히 효과적입니다.
3. 문툴즈
(function(){
var domready = function(){
if (Browser.loaded) return;
Browser.loaded = true;
window.fireEvent('domready');
document.fireEvent('domready');
};
if (Browser.Engine.trident){
var temp = document.createElement('div')
(function( ){
($try(function(){
temp.doScroll('left');
return $(temp).inject(document.body).set('html', 'temp' ).dispose ();
})) ? domready() : 인수.callee.delay(50)
})()
} else if (Browser.Engine.webkit && .version < ; 525){
(function(){
(['loaded', 'complete'].contains(document.readyState)) ? domready() : 인수.callee.delay(50);
})();
} else {
window.addEvent('load', domready)
document.addEvent('DOMContentLoaded', domready)
}
} )() ;
구현 아이디어는 다음과 같습니다. IE인 경우 doScroll 메소드를 사용하여 구현합니다.
Webkit 525 미만 버전인 경우 document.readyState를 폴링하여 구현합니다.
기타(FF/Webkit 상위 버전/Opera)는 DOMContentLoaded 이벤트를 직접 등록합니다.
Moontools의 구현 솔루션 프로토타입과 jQeury가 통합되어 있으며, 웹킷의 버전 판단으로 솔루션이 더욱 견고해집니다. doScroll의 구현 측면에서는 jQuery와 비교하여 여기에 새로운 div 요소가 생성되고 사용 후 소멸됩니다. 그러나 jQuery는 documentElement의 doScroll을 직접 사용하여 감지하는 것이 더 간단하고 효율적입니다.
4. 도장
// DOMContentLoaded 시작
// Mozilla 및 Opera 9에서는
if(document.addEventListener){
// 참고:
// 사용할 수 있는 이벤트를 노출합니다. Firefox 2.0의 스레딩 문제로 인해 해당 플랫폼에서는
// DOMContentLoaded를 활성화할 수 없습니다. 자세한 내용은
// http://trac.dojotoolkit.org/ticket/1704
if(dojo.isOpera || dojo.isFF >= 3 || (dojo.isMoz && dojo. config.enableMozDomContentLoaded === true)){
document.addEventListener("DOMContentLoaded", dojo._loadInit, null);
}
// 주로 Opera 8.5의 경우 DOMContentLoaded가 이미 실행된 경우 실행되지 않습니다.
// Trac #1640 때문에 Mozilla에도 사용됩니다.
window.addEventListener("load", dojo._loadInit, null);
}
if(dojo.isAIR){
window.addEventListener("load", dojo._loadInit, null);
}else if(/(WebKit|khtml)/i.test(navigator.userAgent)){ // 스니핑
dojo._khtmlTimer = setInterval(function(){
if(/loaded|complete/ .test(document.readyState)){
dojo._loadInit(); // 온로드 핸들러 호출
}
}, 10);
}
// END DOMContentLoaded
(function(){
var _w = window;
var _handleNodeEvent = function(/*String*/evtName, /*Function*/fp){
// 요약:
// 지정된 함수를 노드의
// evtName 핸들러에 비파괴적으로 추가합니다.
// evtName: "onclick" 핸들러의 경우 "onclick" 형식이어야 합니다. .
// "on" 부분을 전달해야 합니다.
var oldHandler = _w[evtName] || function(){}; fp.apply(_w, 인수);
oldHandler.apply(_w, 인수);
}
};
if(dojo.isIE){
// ReadyState는 init
// 호출 시 달성되지 않지만 도장에는 필요하지 않으므로 포함하겠습니다
//
/에 추가된 다른 함수가 있는지 모르기 때문에
/ / 빌드 프로세스가
// 조건부 주석을 포함하여 모든 주석을 제거하기 때문에 이것이 변경되었습니다.
if(!dojo.config.afterOnLoad){
document.write('' ''
);
}
시도해 보세요{
document.namespaces.add("v","urn:schemas-microsoft-com:vml");
document.createStyleSheet().addRule("v\:*", "behavior:url(#default#VML)");
}catch(e){}
}
// FIXME: dojo.unloaded에는 dojo 범위가 필요하므로 anon 함수 래퍼를 사용합니다.
_handleNodeEvent("onbeforeunload", function() {
dojo.unloaded();
});
_handleNodeEvent("onunload", function() {
dojo.windowUnloaded();
});
})();
实现思路如下:
如果是Opera或FF3以上版本则直接注册DOMContentLoaded<事件,为保险起见,同时也注册了window.onload事件。 对于webkit则communication轮询document.readyState来实现。
如果是Air则只注册widnow.onload事件。
如果是IE则通过往页face写带defer 준비 상태 변경에 대한 스크립트 실행
Dojo는 IE下의 实现方案同样无法解决iframe의 问题,而由于에서 FF2 下会有一个不常奇怪的Bug, 因此默认只因此默认只因此默认只以上版本上版本上本上에서 ContentLoaded사건, 同时又给了一个配置-dojo.config.enableMozDomContentLoaded, FF下将该配置设置为true则依然会使用 DOMContentLoaded来实现, 这一点充分考虑到了灵活性.实现,与prototype은 모두 존재하는 공간입니다.
五、YUI
复主代码 代码如下:
(function() {
/*! DOMReady: 작업 기반: Dean Edwards/John Resig/Matthias Miller */
// Internet Explorer: 지연된 스크립트의 ReadyState를 사용합니다.
// 이는
// 문서의 ReadyState가 제안하기 전에 DOM을 조작하기에 안전한 순간을 분리합니다.
// 그렇게 하는 것이 안전합니다
(EU.isIE. ) {
//
// DOM이 준비되면 onAvailable/onContentReady 항목을 처리합니다.
YAHOO.util.Event.onDOMReady(
YAHOO.util.Event._tryPreloadAttach,
YAHOO. util.Event, true);
var n = document.createElement('p');
EU._dri = setInterval(function() {
try {
// doc인 경우 오류 발생 준비되지 않음
n.doScroll('left');
clearInterval(EU._dri);
EU._dri = null
n = null;
} catch (예) {
}
}, EU.POLL_INTERVAL)
// 현재 Safari의 문서 ReadyState는
// 이미지가 로드되기 전에 로드/완료로 변경됩니다.
} else if (EU.webkit && EU.webkit < 525) {
EU._dri = setInterval(function() {
var rs=document.readyState;
if ("로드됨" == rs || "완료" == rs) {
clearInterval(EU._dri);
EU._dri = null;
EU._ready();
}
}, EU.POLL_INTERVAL);
// FireFox 및 Opera: 이 브라우저는
// 순간에 대한 이벤트를 제공합니다. 이제 최신 WebKit 릴리스가 이 이벤트를 지원합니다.
} else {
EU._simpleAdd(document, "DOMContentLoaded", EU._ready);
}
///////////////////////////////////////////////////////////////////// //////////////////
EU._simpleAdd(window, "load", EU._load);
EU._simpleAdd(window, "unload", EU._unload);
EU._tryPreloadAttach();
})();
实现思路与Moontools一样
六、EXT
function initDocReady(){
var COMPLETE = "complete";
docReadyEvent = new Ext.util.Event();
if (Ext.isGecko || Ext.isOpera) {
DOC.addEventListener(DOMCONTENTLOADED, fireDocReady, false);
} else if (Ext.isIE){
DOC.write("");
DOC.getElementById(IEDEFERED).onreadystatechange = function(){
if(this.readyState == COMPLETE){
fireDocReady();
}
};
} else if (Ext.isWebKit){
docReadyProcId = setInterval(function(){
if(DOC.readyState == COMPLETE) {
fireDocReady();
}
}, 10);
}
// 무슨 일이 있어도 로드 시 실행되는지 확인하세요.
E.on(WINDOW, "load", fireDocReady);
}
实现思路与Dojo의 一致,不再赘诉。
总结
总结各大主流框架的做法,写了以下这个版本。主要是尽의 무게做到优化并考虑到FF2下的Bug,提供一个是否使用 DOMContentLoaded的开关配置。
/*
* 注册浏览器的DOMContentLoaded事件
* @param { Function } onready [必填]在DOMContentLoaded事件触发时需要执行的函数
* @param { Object } config [可选]配置项
*/
function onDOMContentLoaded(onready,config){
//浏览器检测상关对象,在此为节省代码未实现,实际使用时需要实现.
//var 브라우저 = {};
//设置是否에서 FF下使用 DOMContentLoaded(FF2下的特定场景有Bug)
this.conf = {
enableMozDOMReady:true
};
if( config )
for( var p in config)
this.conf[p] = config[p];
var isReady = false;
function doReady(){
if( isReady ) return;
//确保onready只执行一次
isReady = true;
준비 완료();
}
/*IE*/
if( Browser.ie ){
(function(){
if( isReady ) return;
try {
document.documentElement .doScroll("왼쪽");
} catch( error ) {
setTimeout(args.callee, 0 )
return;
}
doReady()}; ();
window.attachEvent('onload',doReady);
}
/*Webkit*/
else if (Browser.webkit && Browser.version < 525){
(function(){
if( isReady ) return;
if (/loaded|complete/.test(document.readyState))
doReady();
else
setTimeout(args.callee, 0 )
})();
window.addEventListener('load',doReady,false);
}
/*FF Opera 高版webkit 其他*/
else{
if( !Browser.ff || Browser.version != 2 || this.conf.enableMozDOMReady)
document.addEventListener( "DOMContentLoaded", function(){
document.removeEventListener( "DOMContentLoaded", 인수.callee, false );
doReady();
}, false );
window.addEventListener('load',doReady,false);
}
}