> 웹 프론트엔드 > JS 튜토리얼 > 일부 주류 JS Frameworks_jquery의 DOMReady 이벤트 구현 요약

일부 주류 JS Frameworks_jquery의 DOMReady 이벤트 구현 요약

WBOY
풀어 주다: 2016-05-16 18:10:56
원래의
994명이 탐색했습니다.

가장 일반적으로 사용되는 것은 window의 onload 이벤트로, 이 이벤트의 실제 효과는 페이지 구문 분석/DOM 트리 구축이 완료된 후 트리거되고 그림, 스크립트와 같은 모든 리소스가 다운로드되는 것입니다. , 스타일 시트, 심지어 iframe까지 완성되었습니다. 이는 많은 실제 응용 프로그램에 있어서 약간 "너무 늦었고" 사용자 경험에 영향을 미칩니다. 이 문제를 해결하기 위해 ff에 DOMContentLoaded 메서드가 추가되었습니다. onload와 비교하여 이 메서드는 다른 리소스가 로드될 때까지 기다리지 않고 페이지의 DOM 콘텐츠가 로드된 후에 트리거됩니다. Webkit 엔진도 버전 525(Webkit nightly 1/2008:525)부터 이 이벤트를 도입했으며 Opera에도 이 방법이 포함되어 있습니다. 아직까지는 주류 IE에서는 이를 추가할 의사가 없습니다. IE에서는 사용할 수 없지만 항상 해결책이 있습니다. 다음은 이 이벤트에 대한 여러 주요 주류 프레임워크의 호환성 버전 구현 계획을 비교한 것입니다.
프로토타입
jQeury
Moontools
dojo
yui
ext
1. 프로토타입
구현 코드

코드 복사 코드는 다음과 같습니다.

(function() {
/* DOMContentLoaded 이벤트에 대한 지원은 Dan Webb,
Matthias Miller의 작업을 기반으로 합니다. Dean Edwards 및 John Resig */
var 타이머;
function fireContentLoadedEvent() {
if (document.loaded) return
if (timer) window.clearInterval(timer); document.fire("dom :loaded");
document.loaded = true;
}
if (document.addEventListener) {
if (Prototype.Browser.WebKit) {
timer = window.setInterval(function () {
if (/loaded|complete/.test(document.readyState))
fireContentLoadedEvent();
},
Event.observe(window) , "load", fireContentLoadedEvent )
} else {
document.addEventListener("DOMContentLoaded",
fireContentLoadedEvent, false)
}
} else {
document.write( "<" "스크립트 ID=__onDOMContentLoaded defer src=//:>")
$("__onDOMContentLoaded").onreadystatechange = function() {
if (this.readyState = = "완료") {
this.onreadystatechange =
fireContentLoadedEvent()
}
}
})(); 🎜>구현 아이디어는 다음과 같습니다.
웹킷인 경우 문서의 ReadyState 속성을 폴링합니다. 이 속성의 값이 로드되거나 완료되면 안전을 위해 DOMContentLoaded 이벤트가 트리거됩니다. window.onload에 이벤트를 등록하세요.
FF인 경우 DOMContentLoaded 이벤트를 직접 등록하세요.
IE인 경우 document.write를 사용하여 페이지에 스크립트 요소를 추가하고 defer 속성을 설정합니다. 마지막으로 스크립트 로딩 완료를 DOMContentLoaded 이벤트로 간주하여 트리거합니다.
이 구현에는 두 가지 주요 문제가 있습니다. 첫째, document.write를 통해 스크립트를 작성하고 defer를 설정하는 방법은 페이지에 iframe이 포함된 경우 트리거되기 전에 iframe의 콘텐츠가 로드될 때까지 기다립니다. 이는 onload와 다릅니다. 두 번째로 Webkit은 525 이상의 버전에서 DOMContentLoaded 메서드를 도입했으므로 이러한 버전에서는 폴링을 구현할 필요가 없으며 최적화할 수 있습니다.

2. jQuery




코드 복사
코드는 다음과 같습니다. / / 편리한 이벤트 콜백 사용 document.addEventListener( "DOMContentLoaded", function(){ document.removeEventListener( "DOMContentLoaded",args.callee, false ); jQuery.ready() ;
}, false );
// 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的开关配置。

复system代码 代码如下:
/*
* 注册浏览器的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);
}
}

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿