• 页面渲染时js阻塞的解决方法


    一般地,一个包含外部样式表文件和外部脚本文件的HTML载入和渲染过程是这样的:

    1. 浏览器下载HTML文件并开始解析DOM。
    2. 遇到样式表文件link[rel=stylesheet]时,将其加入资源文件下载队列,继续解析DOM。
    3. 遇到脚本文件时,暂停DOM解析并立即下载脚本文件。
    4. 下载结束后立即执行脚本,在脚本中可访问当前<script>以上的DOM。
    5. 脚本执行结束,继续解析DOM。
    6. 整个DOM解析完成,触发DOMContentLoaded事件。

    什么是阻塞?

      在页面中我们通常会引用外部文件,而浏览器在解析HTML页面是从上到下依次解析、渲染,如果<head>中引用了一个a.js文件,而这个文件很大或者有问题,需要2秒加载,那么浏览器会停止渲染页面(此时是白屏显示,就是页面啥都没有),2秒后加载完成才会继续渲染,这个就是阻塞。

    为什么会阻塞?

      因为浏览器不知道a.js中执行了哪些脚本,会对页面造成什么影响,所以浏览器会等js文件下载并执行完成后才继续渲染,如果这个时间过长,会白屏。

    解决方法

    1、推迟加载(延迟加载)

      如果页面初始的渲染并不依赖于js或者CSS可以用推迟加载,就是最后在加载js和css,把引用外部文件的代码写在最后。比如一些按钮的点击事件,比如轮播图动画的脚本也可以放在最后。

    2、defer延迟加载

    <script src="" defer></script>
      在文档解析完成开始执行,并且在DOMContentLoaded事件之前执行完成,会按照他们在文档出现的顺序去下载解析。效果和把script放在文档最后</body>之前是一样的。
              注:defer最好用在引用外部文件中使用,用了defer不要使用document.write()方法;使用defer时最好不要请求样式信息,因为样式表可能尚未加载,浏览器会禁止该脚本等待样式表加载完成,相当于样式表阻塞脚本执行。

    3、异步加载

    • async异步加载:就是告诉浏览器不必等到加载完外部文件,可以边渲染边下载,什么时候下载完成什么时候执行。
       <script type="text/javascript" src="a.js" async></script>
               注:用了async不要使用document.write()方法;使用async时最好不要请求样式信息,原因和defer一样。
    • script dom element法:这个方法是用js动态创建一个script元素添加在document中。
      <script type="text/javascript">
          (function() {
           var s = document.createElement('script');
           s.type = 'text/javascript';
           s.async = true;                                        //这句可以删除,但是效果不变。
           s.src = 'js/a.js';
           var x = document.getElementsByTagName('script')[0];
           x.parentNode.insertBefore(s, x);
       })();
      </script>

      注意:这种方法会阻止onload事件

    • onload时异步加载:这个和script dom element法差不多但是他不是同时执行js和html,他是等html的文件,图片之类的、页面所有的资源全部加载完成后再下载执行js,这样的方法可以避免阻塞onload事件的触发。
       (function() {
            function async_load(){
                var s = document.createElement('script');
                s.type = 'text/javascript';
                s.async = true;
                s.src = 'js/yibujiaz.js';
                var x = document.getElementsByTagName('script')[0];
                x.parentNode.insertBefore(s, x);
            }
            if (window.attachEvent)
                window.attachEvent('onload', async_load);
            else
                window.addEventListener('load', async_load, false);
        })();
      注:DOMContentLoaded与onload事件不同,DOMContentLoaded是页面解析完成,页面的dom元素可以使用,但是页面的图片、视频等资源可能还没加载完成
  • 相关阅读:
    SpringMVC:JSON讲解
    SpringMVC:文件上传和下载
    字符串的使用
    python中的作用域与名称空间
    深、浅copy
    代码块与小数据池之间的关系
    关于敏感字符的筛选替换
    列表的增、删、改、查
    最简三级菜单
    python2.x与python3.x的区别
  • 原文地址:https://www.cnblogs.com/lmjZone/p/8603241.html
Copyright © 2020-2023  润新知