Javascript encapsulates the DOMContentLoaded event instance

  • 2020-03-30 03:18:41
  • OfStack

I recently wrote a Javascript framework that encapsulates the DOMContentLoaded event, gets a little excited, and takes notes on principles and compatibility issues during development.

When we write js code, usually add window. The onload event, mainly to the DOM after loading can use getElementById, getElementsByTagName selection methods such as DOM element, but the window. The load would wait until finish loading the DOM, scripting, CSS, and finally finished loading pictures and even all the resources in the iframe would trigger, a lot of times web images more larger, to wait for the final finish pictures this time consuming large load to perform some js obviously too late, A lot of times it's going to affect the user experience.

Many js frameworks have the function of document.ready, like JQuery's $(document).ready() method, which can execute js code immediately after loading the DOM, and let the image load slowly by itself.

Data say 6 ~ 8 can be used on the document. The document. The onreadystatechange event listeners readyState state is equal to complete to judge whether the DOM to load, if has the iframe, embedded in the page 6 ~ 8 of the document. The readyState will wait to finish all the resources in the iframe loading to become complete, iframe becomes time consuming large at this time. But after testing, even if there is no iframe in the page, it's surprising that when readyState equals complete, the onload event is actually triggered instead of the DOMContentLoaded event.

Fortunately, ie has a special doScroll method. When the doScroll method is called when the DOM of the page is not loaded, it will report an error. Conversely, as long as the doScroll method is called at intervals until no error is reported, it means that the DOM of the page is loaded.

If there are multiple js files bound to the document.ready event, an event queue mechanism can be introduced to prevent the browser from repeating the binding and executing in an orderly manner.

Above is the principle of document.ready event and compatibility issues, the following is attached to the sample code, in order to facilitate the understanding of the execution process, the use of function encapsulation mode, the execution process is written in the comments, if there is any improper welcome to comment.


//Save the domReady event queue
eventQueue = [];

//Determine if the DOM is loaded
isReady = false;

//Determines whether DOMReady is bound
isBind = false;


function domReady(fn){
    if (isReady) {
        fn.call(window);
    }
    else{
        eventQueue.push(fn);
    };

    bindReady();
};


function bindReady(){
    if (isReady) return;
    if (isBind) return;
    isBind = true;

    if (window.addEventListener) {
        document.addEventListener('DOMContentLoaded',execFn,false);
    }
    else if (window.attachEvent) {
        doScroll();
    };
};


function doScroll(){
    try{
        document.documentElement.doScroll('left');
    }
    catch(error){
        return setTimeout(doScroll,20);
    };
    execFn();
};


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 that if the js is loaded asynchronously don't bind the domReady method, otherwise the function won't execute,
//Because the DOMContentLoaded js is fired before the asynchronously loaded js is downloaded, the addEventListener is no longer listening when it executes

Test pages: both load two large images, onload needs to load the image to execute js, and DOMContentLoaded only needs to wait until the DOM is loaded to execute js. Open firebug to view the loading process, and remember to clean up your browser cache before each test.


Related articles: