淺談無阻塞加載腳本方法

無阻塞的腳本是創建響應迅速的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

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