Recently, I was writing a Javascript framework. I just encapsulated the DOMContentLoaded event and was a little excited. I took a note of the Principles and compatibility issues encountered during the development process, saving me the trouble of finding them everywhere.
When writing js code, we usually add windows. the onload event is mainly used to select DOM elements by using methods such as getElementById and getElementsByTagName after DOM loading, but window. load will wait until the DOM, script, and CSS are loaded, and all the resources in the final loaded image or iframe are triggered. In many cases, there are many large images on the webpage, it is obviously too late to execute js after loading the final image, which will affect the user experience in many cases.
Many js frameworks have a document. ready functions, such as JQuery's $ (document ). the ready () method can execute js Code immediately after the DOM is loaded, so that the image can be loaded slowly.
The core of document. ready is the DOMContentLoaded event. For firefox, chrome, opera, safari, and ie9 +, you can use addEventListener ('domaincontentloaded', fn, false) to bind events, whereas ie6 ~ 8 does not support DOMContentLoaded events ~ 8. Perform compatibility processing.
Internet Explorer 6 ~ 8 you can use the document. onreadystatechange event to listen to the document. readyState status to determine whether the DOM has been loaded. If iframe is embedded in the page, ie6 ~ The document. readyState of 8 will be changed to complete after all resources in iframe are loaded. At this time, iframe becomes a time-consuming large user. However, after testing, even if there is no iframe in the page, when readyState is equal to complete, the onload event instead of the DOMContentLoaded event is actually triggered, which is surprising.
Fortunately, ie has a unique doScroll method. When the page DOM is not loaded, an error will be reported when the doScroll method is called. In turn, if you call doScroll at intervals until no error is reported, this method indicates that the page DOM has been loaded, regardless of whether the content in the image or iframe has been loaded.
If multiple js files are bound with the document. ready event, an event queue mechanism can be introduced to prevent repeated browser binding and sequential execution.
The above is document. the principle and compatibility of ready events are described in the following example code. To facilitate understanding of the execution process, the execution process is written in the annotations in the function encapsulation mode, if you have any questions, please feel free to contact us.
Copy codeThe Code is as follows:
// Save the domReady event queue
EventQueue = [];
// Determine whether the DOM has been loaded
IsReady = false;
// Determine whether DOMReady is bound
IsBind = false;
/* Execute domReady ()
*
* @ Param {function}
* @ Execute pushes the event handler to the event queue and binds the DOMContentLoaded
* If the DOM loading is complete, execute it immediately.
* @ Caller
*/
Function domReady (fn ){
If (isReady ){
Fn. call (window );
}
Else {
EventQueue. push (fn );
};
BindReady ();
};
/* DomReady event binding
*
* @ Param null
* @ Execute modern browser bind DOMContentLoaded through addEvListener, including ie9 +
The ie6-8 checks doScroll to determine whether DOM is loaded.
* @ Caller domReady ()
*/
Function bindReady (){
If (isReady) return;
If (isBind) return;
IsBind = true;
If (window. addEventListener ){
Document. addEventListener ('domainloaded', execFn, false );
}
Else if (window. attachEvent ){
DoScroll ();
};
};
/* DoScroll determine whether DOM loading of the ie6-8 is complete
*
* @ Param null
* @ Execute doScroll judge whether DOM loading is complete
* @ Caller bindReady ()
*/
Function doScroll (){
Try {
Document.doc umentElement. doScroll ('left ');
}
Catch (error ){
Return setTimeout (doScroll, 20 );
};
ExecFn ();
};
/* Execution event queue
*
* @ Param null
* @ Execute the event handler in the cyclic execution queue
* @ Caller bindReady ()
*/
Function execFn (){
If (! IsReady ){
IsReady = true;
For (var I = 0; I <eventQueue. length; I ++ ){
EventQueue [I]. call (window );
};
EventQueue = [];
};
};
// Js File 1
DomReady (function (){
...
});
// Js file 2
DomReady (function (){
...
});
// Note: if Javascript is asynchronously loaded, do not bind the domReady method. Otherwise, the function will not be executed,
// Because DOMContentLoaded has been triggered before the asynchronous loading js download, and the addEventListener cannot be listened to during execution
Test page: two large images are loaded. onload requires the image to be loaded before js is executed. DOMContentLoaded only needs to wait until the DOM is loaded to execute js. You can open firebug to view the loading process. Remember to clear the browser cache before each test.