All along, all kinds of JS best practice will tell us that JS is placed in the end of the HTML, that is </body>
, the reason is: JS will block the download, and, in JS is likely to have the operation of the DOM, put in the end of the HTML, as far as possible to ensure that the execution of JS after the completion of the DOM loading. If executed in the OnLoad event, if the page has a lot of images, then the onload event of the page will be too long to trigger, so the DOM ready event is the best time to execute JS.
So, if there is a DOM ready event, although the modern browser has supported the Domcontentloaded event, but we still have to deal with the old browser, so the DOM ready event becomes the necessary function of each JS framework.
Let's take a look at the use of the jquery Dom ready event, which is very simple to use for the DOM well event usage of jquery, and is available in all three of the following syntax:
-
$ (Document . Ready (Handler
-
$ (. Ready (Handler
(not recommended)
-
$ ( Handler )
There is another way: it $(document).on(‘ready‘, handler);
has been deprecated in version 1.8, but you can still use it. This is the same way as the Ready method, but if the handler event has already been triggered, the binding of this method will not be executed, and the handler bound in this manner will be executed after the handler of the above three methods bind.
First, DOM ready detection
Below, we follow the idea of jquery, step-by-step look at how jquery handles the DOM ready event.
1. Standard browser
For standard browsers, we can add domcontentloaded event listeners:
if (document.addeventlistener) { Document.addeventlistener ("domcontentloaded", domcontentloaded, false);}
2. Non-standard browser
For non-standard browsers, we can listen to the Document.onreadystatechange event, and if document.readystate = = ' complete ', you can assume that the DOM structure has been loaded.
if (document.addeventlistener) { Document.addeventlistener ("domcontentloaded", domcontentloaded, false); If IE event model is used} else { document.attachevent ("onreadystatechange", domcontentloaded);}
In the domcontentloaded function, if the condition is met, the Jquery.ready () method is executed, and the event listener is removed.
domcontentloaded = function () { if (document.addeventlistener) { Document.removeeventlistener (" Domcontentloaded ", domcontentloaded, false); Jquery.ready (); } else if (document.readystate = = = "complete") { //we ' re here because readyState = = = "complete" in Oldie //which Is good enough for us to call the DOM ready! Document.detachevent ("onReadyStateChange", domcontentloaded); Jquery.ready (); }};
3. For security reasons
The above detection method should be enough, but in the safety of consideration, in case the previous judgment fails to do. At this time, the OnLoad event may trigger a later, but it can be reliably triggered, so in the judgment added to the OnLoad event monitoring:
if (document.addeventlistener) { Document.addeventlistener ("domcontentloaded", domcontentloaded, false); A fallback to window.onload, that'll always work window.addeventlistener ("Load", Jquery.ready, false); If IE event model is used} else { document.attachevent ("onreadystatechange", domcontentloaded); A fallback to window.onload, that'll always work window.attachevent ("onload", Jquery.ready);}
There is no need to worry that Jquery.ready () will be triggered more than once because there is a detection in Jquery.ready ().
4. or IE
In IE, the onreadystatechange event may be delayed for an IFRAME, but it is safe enough. However, this event is sometimes less reliable for non-IFRAME, especially when the page has more picture resources, it may be triggered after the onload event is triggered, so for this situation, further testing is required:
if (Document.addeventlistener) {Document.addeventlistener ("domcontentloaded", domcontentloaded, false); A fallback to window.onload, that'll always work window.addeventlistener ("Load", Jquery.ready, false); If IE event model is used} else {document.attachevent ("onreadystatechange", domcontentloaded); A fallback to window.onload, that'll always work window.attachevent ("onload", Jquery.ready); If IE and not a frame//continually check to see if the document was ready var top = false; try {top = Window.frameelement = = null && document.documentelement; } catch (e) {}//If the case is non-IFRAME and supports the DoScroll method if (top && top.doscroll) {///in this self-executing function, call Top.doscrol L method, if the error, then delay 50ms re-detection; If you do not make an error, the DOM ready, you can execute the Jquery.ready () method (function Doscrollcheck () {if (!jquery.isre Ady) {try {top.doscroll ("left"); } catch (e) {RetuRN SetTimeout (Doscrollcheck, 50); }//and execute any waiting functions jquery.ready (); } })(); }}
Yes, JS is such a god (Dan) Teng language, each browser implementation may be different, so there is such a monitoring of an event to do so many compatibility considerations.
5. Ready is too late
In another case, when we called the $ (document). Ready (), the DOM structure was loaded and finished, This time can call Jquery.ready directly, but because of IE problem, need to delay the call, so there is the following code, as for why to use, I did not read:
if (document.readystate = = = "complete") {//Handle It asynchronously-allow scripts the opportunity-to-delay ready SetTimeout (Jquery.ready, 1);} else if (Document.addeventlistener) {Document.addeventlistener ("domcontentloaded", domcontentloaded, false); A fallback to window.onload, that'll always work window.addeventlistener ("Load", Jquery.ready, false); If IE event model is used} else {document.attachevent ("onreadystatechange", domcontentloaded); A fallback to window.onload, that'll always work window.attachevent ("onload", Jquery.ready); If IE and not a frame//continually check to see if the document was ready var top = false; try {top = Window.frameelement = = null && document.documentelement; } catch (e) {}//If the case is non-IFRAME and supports the DoScroll method if (top && top.doscroll) {///in this self-executing function, call Top.doscrol L method, if the error, then delay 50ms re-detection; If you do not make an error, the DOM ready, you can execute the Jquery.ready () method (function DoscRollcheck () {if (!jquery.isready) {try {top.doscroll ("left"); } catch (e) {return setTimeout (Doscrollcheck, 50); }//and execute any waiting functions jquery.ready (); } })(); }}
Here, jquery's detection of Dom ready is done, and $ (document). How does ready () work?
Second, DOM ready whole process
Here, we understand the full code of jquery's Dom ready in the order in which the code executes, and see how jquery handles the DOM ready event step-by-step. For the convenience of reading, I have cut the code and made adjustments to the code order, and you can see the code in order from 1 to 7. The deferred object is not explained here, because I have not seen it, just remember that his role is to maintain a series of conditional trigger callback functions.
Jquery.fn = Jquery.prototype = {Init:function (selector, context, rootjquery) {if (Jquery.isfunction (Selec Tor)) {//when calling $ (callback), the $ (document) is called. Ready (callback); Ⅰreturn Rootjquery.ready (selector); }}, Ready:function (FN) {//ADD the callback///Call JQuery.ready.promise method, return a deferred object readylist, The FN is then added to the list of successful callbacks for Readylist. If readylist already exists, it returns readylist directly, and then calls this callback function fn JQuery.ready.promise () Ⅱ directly. Done (FN); Ⅳreturn this; }};jquery.ready.promise = function (obj) {if (!readylist) {readylist = jquery.deferred (); IE bug if (document.readystate = = = "complete") {SetTimeout (Jquery.ready, 1); Bind the domcontentloaded event to the standard browser to trigger the Domcontentloaded method//At the same time, bind the Window.onload event as an alternative} else if (document.ad Deventlistener) {DocumenT.addeventlistener ("domcontentloaded", domcontentloaded, false); Window.addeventlistener ("Load", Jquery.ready, false); Bind the onReadyStateChange event to IE browser, and in domcontentloaded, determine whether the readystate is complete} else {DOCUMENT.A Ttachevent ("onReadyStateChange", domcontentloaded); Window.attachevent ("onload", Jquery.ready); Make further compatibility detection for IE var top = false; try {top = Window.frameelement = = null && document.documentelement; } catch (e) {} if (top && top.doscroll) {(function Doscrollcheck () { if (!jquery.isready) {try {//Use the trick by Diego Perini Http://javascript.nwbox.com/IEContentLoaded/top.doScroll ("left"); } catch (e) {return setTimeout (DOSCROLLCHECK, 50); }//and execute any waiting functions jquery.ready (); } })(); }}}//returns readylist return Readylist.promise (obj); ⅲ};//next is to wait for the domcontentloaded/readystate=== ' complete ' event to occur//Remove Domready event Listener, execute Jquery.ready () domcontentloaded = function () {ⅴ//standard browser if (Document.addeventlistener) {Document.removeeventl Istener ("domcontentloaded", domcontentloaded, false); Jquery.ready (); IE Browser} else if (document.readystate = = = "complete") {document.detachevent ("onreadystatechange", domcontentloaded); Jquery.ready (); }};jquery.extend ({////DOM ready flag bit, after Dom is set to True Isready:false,//Dom ready to run Ready:function () { If it is ready, return directly if (Jquery.isready) {return; }//compatible with IE if (!document.body) {return setTimeout (Jquery.ready, 1); }//Set IsReady to True jquery.isready = true; ⅵ//here is where we really trigger our incoming callbacks!!!! parameter list of incoming context and callback function//Note that the context is document, that is, we are in ' $ ' (document). Ready (FN); ' The This in the FN is ' document ', not ' window '//Parameter The list comes in jquery, meaning that even if we call the ' $.noconflict () ' To get out, we can still define the first parameter in FN as $, which represents the jquery Readylist.resolvewith (document, [Jquer Y]); ⅶ//This code is to trigger the DOM ready callback that was added in this way: $ (document). On (' Ready ', FN); This method is discarded in 1.8, but not removed//you can see that the DOM ready callback added in this way is the last executed if (JQuery.fn.trigger) {jQuery (docum ENT). Trigger ("Ready"). Off ("Ready"); } }});
After reading the code, let's look at the idea of jquery:
- Ⅰ. Calling the Ready event for Rootjquery
- Ⅱ. Call JQuery.ready.promose (), if readylist is empty, assign readylist to a deferred object, otherwise add the callback function to the Readylist success callback list and jump to step 7th
- Ⅲ. Adding listeners to DOM ready events in Jquery.promise ()
- Ⅳ. Adding the callback function fn to the Readylist list of successful callbacks
- Ⅴ. When the DOM Ready event occurs, remove the listener and execute Jquery.ready ()
- Ⅵ. Set IsReady to True in Jquery.ready ()
- Ⅶ. Methods in the list of successful callbacks that perform readylist
"jquery source" DOM ready