提高js在浏览器中的性能(一)

[TOC]

前言

   js脚本的下载和执行会阻塞页面和其他文件的下载,如果不做任何处理那么每一个文件都必须等到前一个文件加载完成并且执行后才开始下载。需要下载的文件一多,页面加载时就会处于卡顿状态,显示一片空白,交互体验非常不好。

解决

1.js加载放置于HTML文档底部

 由于js脚本会阻塞后面文件的加载,因此可以将js脚本的加载放置在整个HTML文档底部,让其最后加载,从而减少对其他文件和页面渲染的阻塞。

 <html>
   <head>
     <title>这是一个网页</title>  
     <link rel="stylesheet" type="text/css" href="">
   </head>
   <body>

    <p>Hello Javascript</p> 
    
   <script type='text/javascript' src=''></script>

   </body>
</html>

2.合并脚本

   尽量减少HTML页面中<script>标签数量(不管是外链接js还是内链接js),浏览器每次遇到一个<script>标签都会加载并执行,我们可以采用合并文件的方式减少<script>的数量,这样只需要一个<script>标签就可以完成页面的交互.

3.延迟脚本

   <script>标签上的defer和async属性可以延迟脚本的执行,并且可以与其他文件并行加载,不会造成阻塞。

<script type='text/javascript' defer></script>
<script type='text/javascript' async></script>

二者区别在于:async属性会在脚本加载完成后自动执行,而defer会等到页面加载完成后执行。
值得注意的是 defer 的执行会在load之前。

4.使用window.onload事件

  window.onload事件会等到页面所有东西都准备完成时执行,可以采用这一机制,在onload事件后加载js脚本,避免js脚本对其他文件的和页面渲染的阻塞。

5.动态创建<script>标签

  采用动态创建的方式添加<script>标签,由于内联代码块是最后执行的,所以插入的<script>标签会在最后加载执行,从而减少了性能的消耗。

<html>
  <head>
    <title>这是一个网页</title>  
    <link rel="stylesheet" type="text/css" href="">
  </head>
  <body>

   <p>Hello Javascript</p> 
   
  <script type='text/javascript' src=''>
     //创建节点
     var script = document.creatElement('script');
     //添加路径
     script.src = '...';
     //插入到head标签中
     document.getElementsByTagName('head')[0].appendChild(script);
  </script>
  </body>
</html>

  我们还可以对其进行封装。
  <scirpt>元素接收完成时会触发一个load事件,因此可以监听脚本加载时的状态。
  IE支持另一个触发事件onreadystatechange事件,<script>元素提供一个readyState属性,该属性有五种状态:

  1. uninitialized:初始状态
  2. loading:开始下载
  3. loaded: 下载完成
  4. interactive:数据玩完成下载但不可用
  5. complete:所有数据都已准备就绪
  /**
  *  动态创建script标签
  * @param{路径} src
  * @param{回调函数} callback
  */
  function scriptLoad(src, callback){
    var scritp = document.creatElement('script');
    if(script.readyState) {
      //IE
      script.onreadystatechange = function (){

        /**IE在标识最终状态的readyState的值时并不一致,有时达到loaded后就不会达到complate,
          又有时,不经过loaded就达到complete,所以这两个值一起检测最好
        */
        if(scritp.readyState == 'loaded' || script.readyState == 'complete'){

            //两个状态只要有个触发就删除事件监听,保证不触发两次
           scritp.onreadystatechang = null;
            //执行回调
           callback();
        }

      }
    }else{
        //其他类型的浏览器
        script.onload = function () {
            callback();
        }

    }

    script.src = src;
    document.head.appendChild(script);
  }

注意:由于动态脚本节点下载文件时,返回的代码通常会自动执行,所以当使用动态加载供其他脚本调用的接口脚本时,就会有问题。

6. 脚本注入

  通过XMLHttpRequest对象获取脚本注入页面之中

  var xhr = new XMLHttpRequest();
  xhr.open('get','路径',true);
  xhr.onreadystatechang = function (e) {
    if(xhr.status >= 200 &&  xhr.status < 300 || xhr == 304){
        var scsript = docment.creatElement('script');
        script.text = xhr.requestText;
        document.head.appendChild(script); 
    }
  }

注意:该方法请求的页面和文件必须处于同一个域。

推荐方法

HTML文档最后,用内联代码写好其他代码的请求方法,然后执行内联代码让其加载其他所需脚本文件。

总结

1.将script标签放置于HTML文档最后。
2.合并脚本,减少HTML中标签的数量。
3.动态加载脚本,此方法一定要注意加载顺序。
4.XMLHttpRequest对象注入,文件和页面一定要处于同一个域下。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。