require.js實現js模塊化編程(一)

一、認識require.js:javascript

官方文檔:http://requirejs.org/
RequireJS是一個很是小巧的JavaScript模塊載入框架,是AMD規範最好的實現者之一。最新版本的RequireJS壓縮後只有14K,堪稱很是輕量。它還同時能夠和其餘的框架協同工做,使用RequireJS必將使您的前端代碼質量得以提高。
RequireJS 是一個JavaScript模塊加載器。它很是適合在瀏覽器中使用, 但它也能夠用在其餘腳本環境, 就像 Rhino and Node. 使用RequireJS加載模塊化腳本將提升代碼的加載速度和質量。html

二、require.js的優勢:前端

  • 2.一、異步加載,防止js阻塞頁面渲染;
  • 2.二、按需加載,避免在初始化網頁的時候,產生大量的請求和數據傳輸;防止出現以下醜陋的場景:

<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

  • 2.三、更加方便的模塊依賴管理。相信你曾經必定遇到過由於script標籤順序問題而致使依賴關係發生錯誤,這個函數未定義,那個變量undefine之類的。經過RequireJS的機制,你能確保在全部的依賴模塊都加載之後再執行相關的文件,因此能夠起到依賴管理的做用。
  • 2.四、更加高效的版本管理。想想,若是你仍是用的script腳本引入的方式來引入一個jQuery2.x的文件,而後你有100個頁面都是這麼引用的,那當你想換成jQuery3.x,那你就不得不去改這100個頁面。可是若是你的requireJS有在config中作jQuery的path映射,那你只須要改一處地方便可。

 三、在網頁中未使用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 從名字就能夠看出這個api是用來定義一個模塊
  • ● require 加載依賴模塊,並執行加載完後的回調函數
  • ● callback,一個function,是用來處理加載完畢後的邏輯

用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的使用方法

  • 6.一、首先要到requirejs的網站去下載js -> requirejs.org或者到個人網盤下載
  • 6.二、而後在index.html頁面中使用下面的方式來使用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也寫上。

  • 6.三、添加全局配置文件main.js

注意:前提是須要在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
})
  • 6.四、a.js實現AMD規範的寫法

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

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

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

加載方法以下:

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

當require()函數加載上面這個模塊的時候,就會先加載a.js文件。

爲何我始終都沒有使用name來定義本身的模塊名:
若是你細心,你可能會發現,剛剛define函數,有一個參數name是用來定義模塊名的(也就是第一個傳參),爲何上面兩個例子都沒有用到。其實我確實能夠添加模塊名,以下:

define('b',['./b'],function(b){
   .....
})

可是,這樣作感受不頗有必要,由於若是哪一天我將這個文件轉移到其餘目錄下,那我就得在這這裏再修改一次模塊名。官方其實也不推薦,用官方的說法是:讓優化工具去自動生成這些模塊名吧!

  • 6.五、加載非規範化模塊

理論上,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,實現具體的項目構建,請自行下載,謝謝關注。

相關文章
相關標籤/搜索