浅谈无阻塞加载脚本方法

无阻塞的脚本是创建响应迅速的web应用的第一步,其秘诀就是在页面加载完成后才加载JS,也就是尽量在window.onload事件触发后再下载脚本。

这里对比几种无阻塞加载脚本的方法

一、延迟的脚本

使用script扩展属性defer,由于只有Internet Explorer 支持 defer 属性,所以基本不建议使用这种方式,使用方法为:

<script defer="defer">

二、XMLHttpRequest脚本注入技术

用XHR来下载JS文件,然后通过创建动态script元素将代码注入页面中:

var xhr = new XMLHttpRequest();
xhr.open("get","file.js",true);
xhr.onreadystatechange = function(){
   if(xhr.readyState == 4){
      //动态添加脚本
      var script = document.createElement("script");
      script.type = "text/javascript";
      script.text = xhr.responseText;
      document.body.appendChild(script);
   }
}

优点:

1、下载JS但不立即执行,可以把脚本的执行推迟到想执行的时候

2、浏览器通用代码,都能正常工作

缺点:

1、js文件要和请求页面处于相同的域,因此大型web应用通常不会采用该技术。

2、需要HTTP请求

三、动态脚本加载

可以直接封装为一个JavaScript,这里我直接叫loadScript.js

function loadScript(urlS,callback){
      //动态加入脚本到
        var script  = document.createElement("script");
        script.type="text/javascript";
        if(script.readyState){  //IE
           script.onreadystatechange = function(){
              if(script.readyState == "loaded" || script.readyState == "complete"){
                  script.onreadystatechange = null;
                  callback();
              }            
           }
        }else{
          script.onload = function(){
              callback();
          };
        }

        script.src = urlS;
        $("head")[0].appendChild(script);
     }

使用方法:

<head>

...

<script src="jq/jquery.min.js"></script>

</head>

<body>

...

<script type="text/javascript">

loadScript("xx.js",function(){
          console.log("动态脚本加载完毕,开始执行其脚本里面的方法初始化");

          //方法代码内容
     });

</script>

</body>

注意:把loadScript函数直接嵌入页面,可以避免产生多一次HTTP请求。

优点:

只需要包含loadScript和一些页面必须脚本代码,下载执行都非常快 

对比可以发现,动态脚本技术的是最最佳方案。下面举个具体栗子来看看真实动态脚本加载使用。

我改装一下我之前一篇文章(https://blog.csdn.net/nzzl54/article/details/91040781)写的html

<head>
...
<link rel="stylesheet" type="text/css" href="ztree/css/zTreeStyle/zTreeStyle.css">
  <script src="jq/jquery.min.js"></script>
  <script src="loadScript.js"></script>
 </head>

<body>
  <div>选择的是:<input id = "xmtShow" type="text" value = "" style="margin-left:10px;margin-top:10px;width: 160px;"></input></div>
  <div class = "tree-content scrollbar" style = "margin-top: 40px;">
    <input hidden id="xmtHide" name="xmt">
    <input id="xmtQuery" type="text" value="" style="margin-left:10px;margin-top:10px;height:18px;line-height:18px;vertical-align:bottom;">
    <input id="xmtQbut" class="xmtQbut" type="button" value="查询">
    <input id="xmtCbut" class="xmtQbut" type="button" value="重置">
    <ul id="xmtTree" class="ztree scrollbar" style="margin-top:0;">
    </ul>
  </div>
  <script type="text/javascript">
    var zNodes = [{id: 1,name: "一级标题1",pId: 0,open:true
      }, {id: 2, name: "一级标题2",pId: 0,open:true
      }, {id: 3, name: "2.1级标题",pId: 2
      }, {id: 4, name: "2.2级标题",pId: 2
      }, {id: 5, name: "1.1级标题", pId: 1
      }, {id: 6, name: "1.2级标题",pId: 1
      }, {id: 7, name: "1.21级标题",pId: 6
      }, {id: 8, name: "一级标题3",pId: 0
      }, {id: 9, name: "1.22级标题",pId: 6
      }, {id: 10, name: "1.221级标题", pId: 9
      }, {id: 11, name: "1.2211级标题", pId: 10
      }, {id: 12, name: "1.2212级标题", pId: 10 } ];
    
     function setTreeQueryInit(){
        var setting = {
                    view: {
                        dblClickExpand: false,
                        showLine: false
                     },
                     data: {
                        simpleData: {
                            enable: true
                        }
                    },
                    check: {
                        enable: false,
                        chkboxType: { "Y": "ps", "N": "s" }
                    },
                    callback: {
                        onClick: myClick,
                        onCheck: onCheck
                    }
                };
        $("#xmtQbut").on('click',function(){//查询项目
                    var keyword=$("#xmtQuery").val();
                    var zNodeQuery=[];
                    if(keyword!=""){
                        for(var i=0;i<zNodes.length;i++){
                            if(zNodes[i].name.indexOf(keyword)!=-1){
                                zNodeQuery.push(zNodes[i]);
                            }
                        }
                    }
                    $("#xmtTree").empty();
                    //alert("123");
                    $.fn.zTree.init($("#xmtTree"), setting, zNodeQuery);
                });

                $("#xmtCbut").on('click',function(){//重置项目
                    $("#xmtQuery").val("");
                    $.fn.zTree.init($("#xmtTree"), setting, zNodes);
                });
     }
    
    function myClick(event, treeId, treeNode){
        console.log(event);
        console.log(treeNode);
        var deptId = treeNode.id;
        console.log(deptId);
        var zTree = $.fn.zTree.getZTreeObj(treeId);
        var names = "";
         var ids = "";
      var nodes;
      if (zTree.setting.check.enable == true) {
         zTree.checkNode(treeNode, !treeNode.checked, false);
         nodes = zTree.getCheckedNodes();
      } else{
         nodes = zTree.getSelectedNodes();
      }
      for (var i = 0, l = nodes.length; i < l; i++) {
        names += nodes[i].name + ",";
        ids += nodes[i].id + ",";
      }
      if (names.length > 0) {
        names = names.substring(0, names.length - 1);
        ids = ids.substring(0, ids.length - 1);
      }
      console.log("names = "+names+",ids = "+ids);
      $("#xmtHide").attr("value",names);
      $("#xmtHide").attr("ids",ids);
      $("#xmtShow").attr("value",names);
      $("#xmtShow").attr("ids",ids);
     }

  loadScript("ztree/js/jquery.ztree.all.js",function(){
      console.log("ztree/js/jquery.ztree.all.js动态脚本加载完成");
      loadScript("plugin/js/selectTreeM.js",function(){
          console.log("动态脚本加载完毕,开始执行其脚本里面的方法初始化");
          initTree("xmtTree",zNodes,myClick,false);
          setTreeQueryInit();
     });
  });
     
  </script>
</body>

主要是把引入loadScript.js,然后在script中直接使用器提供的函数来进行动态加载

 loadScript("ztree/js/jquery.ztree.all.js",function(){
      console.log("ztree/js/jquery.ztree.all.js动态脚本加载完成");
      loadScript("plugin/js/selectTreeM.js",function(){
          console.log("动态脚本加载完毕,开始执行其脚本里面的方法初始化");
          initTree("xmtTree",zNodes,myClick,false);
          setTreeQueryInit();
     });
  });

注意:第三种方法非常适用于一个页面加载多个JavaScript的情况,不过需要注意好脚本间的关系,就像上面的selectTreeM.js是需要先加载完毕ztree/js/jquery.ztree.all.js才能执行

增强版库类LazyLoad下载地址:https://github.com/rgrove/lazyload

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章