一、認識require.js:javascript
官方文檔:http://requirejs.org/
RequireJS是一個很是小巧的JavaScript模塊載入框架,是AMD規範最好的實現者之一。最新版本的RequireJS壓縮後只有14K,堪稱很是輕量。它還同時能夠和其餘的框架協同工做,使用RequireJS必將使您的前端代碼質量得以提高。
RequireJS 是一個JavaScript模塊加載器。它很是適合在瀏覽器中使用, 但它也能夠用在其餘腳本環境, 就像 Rhino and Node. 使用RequireJS加載模塊化腳本將提升代碼的加載速度和質量。html
二、require.js的優勢:前端
<script type="text/javascript" src="a.js"></script>
<script type="text/javascript" src="b.js"></script>
<script type="text/javascript" src="c.js"></script>
<script type="text/javascript" src="d.js"></script>java
三、在網頁中未使用require.js和使用require.js比較jquery
網頁中未使用require.js編寫方式:編程
index.html:api
<!DOCTYPE html> <html> <head> <script type="text/javascript" src="a.js"></script> </head> <body> <span>body</span> </body> </html>
a.js:數組
function fun1(){ alert("it works"); } fun1();
可能你更喜歡這樣寫:瀏覽器
a.js:服務器
(function(){ function fun1(){ alert("it works"); } fun1(); })()
第二種方法使用了塊做用域來申明function防止污染全局變量,本質仍是同樣的,當運行上面兩種例子時不知道你是否注意到,alert執行的時候,html內容是一片空白的,即<span>body</span>並未被顯示,當點擊肯定後,纔出現,這就是JS阻塞瀏覽器渲染致使的結果。
使用require.js寫法:
index.html
<!DOCTYPE html> <html> <head> <script type="text/javascript" src="require.js"></script> <script type="text/javascript"> require(["a"]); </script> </head> <body> <span>body</span> </body> </html>
a.js
define(function(){ function fun1(){ alert("it works"); } fun1(); })
瀏覽器提示了"it works",說明運行正確,可是有一點不同,此次瀏覽器並非一片空白,body已經出如今頁面中。
四、熟悉requirejs基本API
require會定義三個變量:define,require,requirejs,其中require === requirejs,通常使用require更簡短;
一個回調函數:callback
用define定義模塊的方法以下:【function定義法】
若是index.html,main.js,js文件夾爲平級目錄,a.js和jquery.js位於js文件夾下,
a.js【AMD規範的寫法】
define(function() { var target = null; function countTool() { target = this; target.value = 0; }; countTool.prototype.add = function(a, b) { return a + b; }; countTool.prototype.minus = function(a, b) { return a - b; }; return countTool; });
用require 加載依賴模塊,沒有用到callback回調函數,方法以下:
main.js
require(["js/a"]);
來加載該模塊(注意require中的依賴是一個數組,即便只有一個依賴,你也必須使用數組來定義).
require API的第二個參數是callback,一個function,是用來處理加載完畢後的邏輯,如:
main.js
require(["js/a"],function(countTool){ countTool.add(2,3); })
會獲得結果爲:5
如上的寫法,咱們發現require()第一個數組的參數中,添加的a.js的寫法["js/a"]較繁瑣。但可使用require.config()來進行優化。
五、用require.config()來加載文件
以前的例子中加載模塊都是本地js,可是大部分狀況下網頁須要加載的JS可能來自本地服務器、其餘網站或CDN,這樣就不能經過這種方式來加載了,咱們以加載一個jquery庫爲例:
main.js
require.config({ paths : { "jquery" : ["http://libs.baidu.com/jquery/2.0.3/jquery"], // paths還能夠配置多個路徑,若是遠程cdn庫沒有加載成功,能夠加載本地的庫,以下: // "jquery" : ["http://libs.baidu.com/jquery/2.0.3/jquery", "js/jquery"], "a" : "js/a" } }) require(["jquery","a"],function($,a){ $(function(){ a.add(2,3); // 5 }) })
在使用requirejs時,加載模塊時不用寫.js後綴的,固然也是不能寫後綴
六、requirejs的使用方法
<script data-main="js/main" src="js/require.js" defer async="true"></script>
相關參數解析以下:
(1)、加載requirejs腳本的script標籤加入了data-main屬性,是指當reuqire.js加載完成以後,就可使用這個配置文件(main.js)來直接使用require來加載全部的短模塊名。
(2)、當script標籤指定data-main屬性時,require會默認的將data-main指定的js爲根路徑,是什麼意思呢?如上面的data-main="js/main"設定後,咱們在使用require(['jquery'])後(不配置jquery的paths),require會自動加載js/jquery.js這個文件,而不是jquery.js,至關於默認配置了:
require.config({ baseUrl : "js" })
(3)、async屬性代表這個文件須要異步加載,避免網頁失去響應。
(4)、IE的異步加載,只支持defer,因此把defer也寫上。
注意:前提是須要在js/libs文件夾下放入jquery.js和a.js,而且a.js要實現AMD規範的寫法,參照上面的a.js.
main.js
require.config({ paths : { "jquery" : "./libs/js/jquery", "a" : ".libs/js/a" } }) require(["jquery","a"],function($,a){ console.log($); a.add(2,3); // 5 })
另一種優化paths的方法爲:使用參數baseUrl,前提是js/jquery.js,js/a.js以下:另一種優化paths的方法爲:使用參數baseUrl,前提是js/jquery.js,js/a.js以下:
main.js
require.config({ baseUrl: "js/lib", paths: { "jquery": "jquery", "a": "a" } }); require(["jquery","a"],function($,a){ console.log($); a.add(2,3); // 5 })
require.js加載的模塊,採用AMD規範。也就是說,模塊必須按照AMD的規定來寫。
具體來講,就是模塊必須採用特定的define()函數來定義。若是一個模塊不依賴其餘模塊,那麼能夠直接定義在define()函數之中。
require定義一個模塊是經過 define = function (name, deps, callback)完成的,第一個參數是定義模塊名,第二個參數是傳入定義模塊所須要的依賴,第三個函數則是定義模塊的主函數,主函數和require的回調函數同樣,一樣是在依賴加載完之後再調用執行。
以下,沒有依賴模塊的寫法。假定如今有一個a.js文件,它定義了一個a模塊。那麼,a.js就要這樣寫:
a.js 寫法一: 直接定義方法
define(function (){ // 加法 var add = function (x,y){ return x+y; }; // 減法 var minus = function(x,y){ return x-y; } return { add: add, minus:minus }; });
a.js 寫法二: 方法衍生法
define(function() { var target = null; function countTool() { target = this; target.value = 0; }; countTool.prototype.add = function(a, b) { return a + b; }; countTool.prototype.minus = function(a, b) { return a - b; }; return countTool; });
a.js 寫法三: 對象定義法
define(function() { var module = {}; module.value = 0; //加法 var add = function(a, b) { return a + b; } //減法 var minus = function(a, b) { return a - b; } module.add = add; module.minus = minus; return module; });
加載方法以下:
main.js
require(['a'], function (a){ alert(a.add(1,1)); // 2 });
若是這個模塊還依賴其餘模塊,那麼define()函數的第一個參數,必須是一個數組,指明該模塊的依賴性。
依賴對象定義,如: b.js,假設b.js中定義乘法和除法方法。
define(['./b'], function(b) { var module = {}; var add = a.add; //加法 var minus = a.minus; //減法 var multi = b.multi; // 乘法 var division = b.division; // 除法 module.add = add; module.minus = minus; module.multi = multi ; module.division = division; return module; });
當require()函數加載上面這個模塊的時候,就會先加載a.js文件。
爲何我始終都沒有使用name來定義本身的模塊名:
若是你細心,你可能會發現,剛剛define函數,有一個參數name是用來定義模塊名的(也就是第一個傳參),爲何上面兩個例子都沒有用到。其實我確實能夠添加模塊名,以下:
define('b',['./b'],function(b){ ..... })
可是,這樣作感受不頗有必要,由於若是哪一天我將這個文件轉移到其餘目錄下,那我就得在這這裏再修改一次模塊名。官方其實也不推薦,用官方的說法是:讓優化工具去自動生成這些模塊名吧!
理論上,require.js加載的模塊,必須是按照AMD規範、用define()函數定義的模塊。可是實際上,雖然已經有一部分流行的函數庫(好比jQuery)符合AMD規範,更多的庫並不符合。那麼,require.js是否可以加載非規範的模塊呢?
回答是能夠的。
那麼如何判斷一個js庫,有沒有采用AMD規範?只需看其js庫中,有沒有實現define.amd相關的判斷代碼便可;
如jQuery中實現AMD的代碼以下:
if ( typeof define === "function" && define.amd ) { define( "jquery", [], function() { return jQuery; } ); }
underscore.js v1.6中AMD的代碼以下:
if (typeof define === 'function' && define.amd) { define('underscore', [], function() { return _; }); }
jQuery 從 1.7 版本開始支持了 AMD 對其類庫的加載,因此開發者能夠經過 require 方法來異步加載 jQuery 的源代碼。
underscore.js從1.6,backbone.js從1.1.1版本以後開始支持了 AMD 對其類庫的加載;
例如,若是用到underscore.js v1.6或者backbone.js v1.1.1以前的版本,這樣的模塊在用require()加載以前,要先用require.config()方法,定義它們的一些特徵。這裏須要用到shim{},專門用來配置不兼容的模塊,以下:
require.config({ shim: { 'underscore':{ exports: '_' }, 'backbone': { deps: ['underscore', 'jquery'], exports: 'Backbone' }, 'jquery.scroll': { deps: ['jquery'], exports: 'jQuery.fn.scroll' } } });
如:dateUtil.js,沒有用define()來定義。
(function(window) { var DateUtils = {}; DateUtils.toString = function() { alert("toString"); }; // 全局變量 window.DateUtils = DateUtils; })(window);
加載該模塊的方法以下:
require.config({ shim:{ dateUtil:{ deps:[], exports:'dateUtil' } } });
具體來講,每一個模塊要定義
(1)deps數組,代表該模塊的依賴性。
(2)exports值(輸出的變量名),代表這個模塊外部調用時的名稱;
七、require.js提供了一個優化工具r.js
require.js提供了一個優化工具r.js或者到網盤下載,當模塊部署完畢之後,能夠用這個工具將多個模塊合併在一個文件中,減小HTTP請求數。
具體使用方法,請參考下節:require.js實現js模塊化編程(二):RequireJS Optimizer
八、相關文檔:
require.js,實現具體的項目構建,請自行下載,謝謝關注。