• DOMContentLoaded vs jQuery.ready vs onload, How To Decide When Your Code Should Run


    At a Glance

    • Script tags have access to any element which appears before them in the HTML.
    • jQuery.ready / DOMContentLoaded occurs when all of the HTML is ready to interact with, but often before its been rendered to the screen.
    • The load event occurs when all of the HTML is loaded, and any subresources like images are loaded.
    • Use setTimeout to allow the page to be rendered before your code runs.

    Deep Dive

    The question of when your JavaScript should run comes down to ‘what do you need to interact with on the page?’.

    Scripts have access to all of the elements on the page which are defined in the HTML file before the script tag. This means, if you put your script at the bottom of the <body> you know every element on the page will be ready to access through the DOM:

    <html>
      <body>
        <div id="my-awesome-el"></div>
    
        <script>
          document.querySelector('#my-awesome-el').innerHTML = new Date
        </script>
      </body>
    </html>
    

    This works just as well for external scripts (specified using the src attribute).

    If, however, your script runs before your element is defined, you’re gonna have trouble:

    <html>
      <body>
        <script>
          document.querySelector('#my-awesome-el').innerHTML = new Date
          /* ERROR! */
        </script>
    
        <div id="my-awesome-el"></div>
      </body>
    </html>
    

    There’s no technical difference between including your script in the <head> or <body>, all that matters is what is defined before the script tag in the HTML.

    When All The HTML/DOM Is Ready

    If you want to be able to access elements which occur later than your script tag, or you don’t know where users might be installing your script, you can wait for the entire HTML page to be parsed. This is done using either the DOMContentLoaded event, or if you use jQuery, jQuery.ready (sometimes referred to as $.ready, or just as $()).

    <html>
      <body>
        <script>
          window.addEventListener('DOMContentLoaded', function(){
            document.querySelector('#my-awesome-el').innerHTML = new Date
         });
        </script>
    
        <div id="my-awesome-el"></div>
      </body>
    </html>
    

    the same script using jQuery:

    jQuery.ready(function(){
      document.querySelector('#my-awesome-el').innerHTML = new Date
    });
    
    // OR
    
    $(function(){
      document.querySelector('#my-awesome-el').innerHTML = new Date
    });
    

    It may seem a little odd that jQuery has so many syntaxes for doing the same thing, but that’s just a function of how common this requirement is.

    Run When a Specific Element Has Loaded

    DOMContentLoaded/jQuery.ready often occurs after the page has initially rendered. If you want to access an element the exact moment it’s parsed, before it’s rendered, you can use MutationObservers.

    var MY_SELECTOR = ".blog-post" // Could be any selector
    
    var observer = new MutationObserver(function(mutations){
      for (var i=0; i < mutations.length; i++){
        for (var j=0; j < mutations[i].addedNodes.length; j++){
          // We're iterating through _all_ the elements as the parser parses them,
          // deciding if they're the one we're looking for.
          if (mutations[i].addedNodes[j].matches(MY_SELECTOR)){
            alert("My Element Is Ready!");
    
            // We found our element, we're done:
            observer.disconnect();
          };
        }
      }
    });
    
    observer.observe(document.documentElement, {
      childList: true,
      subtree: true
    });
    

    As this code is listening for when elements are rendered, the MutationObserver must be setup before the element you are looking for in the HTML. This commonly means setting it up in the <head> of the page.

    For more things you can do with MutationObservers, take a look at our article on the topic.

    Run When All Images And Other Resources Have Loaded

    It’s less common, but sometimes you want your code to run when not just the HTML has been parsed, but all of the resources like images have been loaded. This is the time the page is fully rendered, meaning if you do add something to the page now, there will be a noticable ‘flash’ of the page before your new element appears.

    window.addEventListener('load', function(){
      // Everything has loaded!
    });
    

    Run When A Specific Image Has Loaded

    If you are waiting on a specific resource, you can bind to the load event of just that element. This code requires access to the element itself, meaning it should appear after the element in the HTML source code, or happen inside a DOMContentLoaded or jQuery.ready handler function.

    document.querySelector('img.my-image').addEventListener('load', function(){
      // The image is ready!
    });
    

    Note that if the image fails to load for some reason, the load event will never fire. You can, however, bind to the error event in the same manner, allowing you to handle that case as well.

    Run When My Current Changes Have Actually Rendered

    Changes you make in your JavaScript code often don't actually render to the page immediately. In the interest of speed, the browser often waits until the next event loop cycle to render changes. Alternatively, it will wait until you request a property which will likely change after any pending renders happen.. If you need that rendering to occur, you can either wait for the next event loop tick;

    setTimeout(function(){
      // Everything will have rendered here
    });
    

    Or request a property which is known to trigger a render of anything pending:

    el.offsetHeight // Trigger render
    
    // el will have rendered here
    

    The setTimeout trick in particular is also great if you’re waiting on other JavaScript code. When your setTimeout function is triggered, you know any other pending JavaScript on the page will have executed.

  • 相关阅读:
    UVa
    UVa 1630
    P3891 [GDOI2014]采集资源
    一个非常naive的小学数学魔术证明题
    P2831 [NOIP2016 提高组] 愤怒的小鸟
    P4211 [LNOI2014]LCA
    P4137 Rmq Problem / mex 强制在线做法
    P2272 [ZJOI2007]最大半连通子图
    P5664 [CSP-S2019] Emiya 家今天的饭
    盘点linux操作系统中的10条性能调优命令,一文搞懂Linux系统调优
  • 原文地址:https://www.cnblogs.com/pptu/p/11983686.html
Copyright © 2020-2023  润新知