使用RequireJS庫載入JavaScript模組的執行個體教程_javascript類庫

來源:互聯網
上載者:User

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.config配置模組對應的路徑
  • require聲明依賴關係

html demo

<script src ="js/require.js" defer async="true" data-main="js/main" ><!--給出requirejs路徑,聲明為非同步載入,指定入口模組為main.js(可省略.js)-->

main.js

 require.config({   //聲明模組的位置   paths: {     "jquery":"libs/jquery"     "login" : "libs/login"   }   //或使用baseUrl指定所有模組的路徑   baseUrl: "js/libs" }); //使用require載入模組,第一個參數為數組,即要載入的模組,將按數組順序載入;第二個為回呼函數,在全部載入完成後執行。 require(['jquery','login'],function($,Login){   alert("jquery and login module load success!");   Login.do_login();   //some else });

符合amd的login module定義

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

rails沒有應用js載入器,一方面是新版本的rails的asset pipe會將所有的js檔案打包為一個js檔案,沒有多個js載入的狀態,另一方面turbolink使用褒貶參半的所謂pjax技術,預設連結改為ajax方式,只擷取html的bod部分,head部分不變動,使js的載入只在第一次開啟網站時進行。


案例一: 載入 JavaScript 檔案

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

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

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

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

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

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

案例三:RequireJS 插入的 < script>

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

使用 RequireJS 來定義 JavaScript 模組

這裡的 JavaScript 模組與傳統的 JavaScript 代碼不一樣的地方在於它無須訪問全域的變數。模組化的設計使得 JavaScript 代碼在需要訪問”全域變數”的時候,都可以通過依賴關係,把這些”全域變數”作為參數傳遞到模組的實現體裡,在實現中就避免了訪問或者聲明全域的變數或者函數,有效避免大量而且複雜的命名空間管理。

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

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

案例四: student 模組,student.js

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

案例五:class 模組,class.js

 

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

案例六: 主程式

 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  });

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

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

 

define(["js/student", "js/class"], function(student, clz){  return {   addNewStudent: function(name, gender){   clz.addToClass(student.createStudent(name, gender));     },   getMyClassSize: function(){   return clz.getClassSize();   }    };  });

案例八:新的主程式

 require(["js/manager"], function(manager) {  manager.addNewStudent("Jack", "male");  manager.addNewStudent("Rose", "female");  console.log(manager.getMyClassSize());// 輸出 2  });

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

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

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

require(”dependencyModuleName”)

配置 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 的官方網站查閱相關文檔。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.