首頁  >  文章  >  web前端  >  使用RequireJS庫載入JavaScript模組的實例教學

使用RequireJS庫載入JavaScript模組的實例教學

高洛峰
高洛峰原創
2016-12-28 14:15:17997瀏覽

js透過script標籤的預設載入方式是同步的,也就是第一個script標籤內的js載入完成後,才開始載入第二個,以此類推,直到js檔案全部載入完畢。而js的依賴關係必須透過script的順序才能確保;而在js載入期間,瀏覽器將停止回應,這大大影響了使用者體驗,基於此,許多解決js以來和載入的方案出現,require js就是其中之一。

requirejs載入的模組,一般為符合AMD標準的模組,即用define定義,用ruturn返回暴露方法、變數的模組;requirejs也可以載入飛AMD標準的模組,但比較麻煩,這次不涉及。

require載入js主涉及以下方面:

script 標籤data-main屬性聲明requirejs載入的入口模組,async="true"(非ie) 和defer(ie)標籤表示非同步載入。

require。的rails的asset pipe會將所有的js文件打包為一個js文件,沒有多個js加載的狀態,另一方面turbolink使用褒貶參半的所謂pjax技術,默認鏈接改為ajax方式,只獲取html的bod部分,head部分不變動,使js的載入只在第一次開啟網站時進行。

案例一: 載入JavaScript 檔案

<script src ="js/require.js" defer async="true" data-main="js/main" >
 
<!--给出requirejs路径,声明为异步加载,指定入口模块为
 
main.js(可省略.js)-->

require 方法裡的這個字串陣列參數可以允許不同的值,當字串是以」.js」結尾,或以」/」開頭,或就是一個URL 時,RequireJS 會認為使用者正在直接載入一個JavaScript 文件,否則,當字串是類似」my/module」的時候,它會認為這是一個模組,並且會以使用者配置的baseUrl 和paths 來載入對應的模組所在的JavaScript 檔。配置的部分會在稍後詳細介紹。

這裡要指出的是,RequireJS 預設情況下並沒有保證myFunctionA 和myFunctionB 一定是在頁面加載完成以後執行的,在有需要保證頁面加載以後執行腳本時,RequireJS 提供了一個獨立的domReady 模組,需要去RequireJS 官方網站下載這個模組,它並沒有包含在RequireJS 中。有了 domReady 模組,案例一 的程式碼稍做修改加上對 domReady 的依賴就可以了。

案例二: 頁面載入後執行JavaScript

require.config({
  //声明模块的位置
  paths: {
    "jquery":"libs/jquery"
    "login" : "libs/login"
  }
  //或使用baseUrl指定所有模块的路径
  baseUrl: "js/libs"
});
//使用require加载模块,第一个参数为数组,即要加载的模块,将按数组顺序加载;第二个为回调函数,在全部加载完成后执行。
require([&#39;jquery&#39;,&#39;login&#39;],function($,Login){
  alert("jquery and login module load success!");
  Login.do_login();
  //some else
});

執行案例二的程式碼後,透過Firebug 可以看到RequireJS 會在目前的頁面上插入為a.js 和b.js 分別宣告了一個 標籤,用於非同步方式下載JavaScript 檔案。 async 屬性目前絕大部分瀏覽器已經支持,它表明了這個 標籤中的 js 檔案不會阻塞其他頁面內容的下載。


案例三:RequireJS 插入的

//依赖jquery的定义
 define([&#39;jquery&#39;],function($){
   // some definations
  function do_login(){
    $.post(&#39;/sessions/create&#39;,{uname:$("#uname").val(),
         password:$("#password").val()},function(data){
     //some 
   });
   return {do_login:do_login};
  } 
 });
 
//不依赖其他模块的定义
define(function(){
 //some definations
 return {xx:xx};
});

使用 RequireJS 來定義 JavaScript 模組

這裡的 JavaScript 模組與傳統的 JavaScript 程式碼不一樣的地方在於它無須存取全域的變數。模組化的設計使得JavaScript 程式碼在需要存取」全域變數」的時候,都可以透過依賴關係,把這些」全域變數」當作參數傳遞到模組的實作體裡,在實作中就避免了存取或宣告全域的變數或函數,有效的避免大量且複雜的命名空間管理。

如同 CommonJS 的 AMD 規範所述,定義 JavaScript 模組是透過 define 方法來實現的。

下面我們先來看一個簡單的例子,這個例子透過定義一個 student 模組和一個 class 模組,在主程式中實作建立 student 物件並將 student 物件放到 class 中去。

案例四: student 模組,student.js

<script src="./js/require.js"></script> 
  <script> 
 require(["./js/a.js", "./js/b.js"], function() { 
      myFunctionA(); 
      myFunctionB(); 
   }); 
  </script>

案例五:class 模組,class.js

<script src="./js/require.js"></script> 
  <script> 
 require(["domReady!", "./js/a.js", "./js/b.js"], function() { 
      myFunctionA(); 
      myFunctionB(); 
   }); 
  </script>

案例六: 主程式

<script type="text/javascript" charset="utf-8" async="" data-requirecontext="_"
data-requiremodule="js/a.js" src="js/a.js"></script>

student 模組和class 模組都是獨立的模組,下面我們再定義一個新的模組,這個模組依賴student 和class 模組,這樣主程式部分的邏輯也可以包裝進去了。

案例七: 依賴student 和class 模組的manager 模組,manager.js

define(function(){ 
  return { 
   createStudent: function(name, gender){ 
      return { 
        name: name, 
        gender: gender 
      }; 
   } 
  }; 
});

案例八:新的主程式

define(function() { 
 var allStudents = []; 
    return { 
      classID: "001", 
      department: "computer", 
      addToClass: function(student) { 
      allStudents.push(student); 
      }, 
      getClassSize: function() { 
      return allStudents.length; 
      } 
    }; 
   } 
 );

透過上面的程式碼範例,我們已經清楚的了解如何寫一個模組,這個模組如何被使用,模組間的依賴關係如何定義。還是有一些使用技巧需要提示一下:

盡量不要提供模組的ID,如AMD 規範所述,這個ID 是可選項,如果提供了,在RequireJS 的實作中會影響模組的可遷移性,檔案位置變化會導致需要手動修改該ID。

每個 JavaScript 檔案只定義一個模組,模組名稱和檔案路徑的查找演算法決定了這種方式是最優的,多個的模組和檔案會被優化器進行最佳化。 避免模​​組的循環依賴,如果實在避免不了,可以模組中加上對”require”模組的依賴,在程式碼中直接用

require(["js/student", "js/class"], function(student, clz) { 
clz.addToClass(student.createStudent("Jack", "male")); 
clz.addToClass(student.createStudent("Rose", "female")); 
console.log(clz.getClassSize()); // 输出 2 
});

配置 RequireJS:

前面的介绍中,我们似乎忽略了一个基本问题,模块名字是怎么来的?当我在 require 一个模块时,这个模块是如何映射到具体的 JavaScript 文件上去?这就涉及到如何配置 RequireJS。

最简化的加载 RequireJS 的方式如案例2 所示,在这种情况下,我们没有指定一个 baseUrl 和 paths 给 RequireJS,如果通过如案例10 所示方式,则 data-main 指定了一个在当前 index.html 目录并行的文件夹下的 /js/main.js 作为程序入口,而 /js 目录也将作为 baseUrl 在其他模块定义时候使用。

案例九:载入 require.js

<script data-main="js/main" src="scripts/require.js"></script>

因此,我们前面示例中的所有模块依赖,都可以去掉”js/”,直接写 ”student”, ”class”,”manager” 等。 一种更为直接的方式显示指定 baseUrl 和 paths 就是利用 require.config 来设置这些参数。如案例十 所示。

案例十. 配置 RequireJS

<script type="text/javascript" src="./js/require.js"></script> 
<script type="text/javascript"> 
require.config({ 
 baseUrl: "./js", 
 paths: { 
   "some": "some/v1"
 }, 
waitSeconds: 10 
}); 
require( ["some/module", "my/module", "./js/a.js"], 
 function(someModule,  myModule) {} 
); 
</script>

baseUrl指明的是所有模块的 base URL,比如”my/module”所加载的 script实际上就是 /js/my/module.js。注意,以 .js 结尾的文件加载时不会使用该 baseUrl,它们仍然会使用当前 index.html所在的相对路径来加载,所以仍然要加上”./js/”。如果 baseUrl没有指定,那么就会使用 data-main中指定的路径。

paths 中定义的路径是用于替换模块中的路径,如上例中的 some/module 具体的 JavaScript 文件路径是 /js/some/v1/module.js 。 waitSeconds 是指定最多花多长等待时间来加载一个 JavaScript 文件,用户不指定的情况下默认为 7 秒。

另外一个重要的配置是 packages,它可以指定其他符合 CommonJS AMD 规范的目录结构,由此带来了丰富的扩展性。如 Dojo、jQuery 等的模块也可以通过该配置来让 RequireJS 加载。

其他可配置的选项还包括 locale、context、deps、callback等,有兴趣的读者可以在 RequireJS 的官方网站查阅相关文档。

更多使用RequireJS库加载JavaScript模块的实例教程相关文章请关注PHP中文网!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn