JS模塊化開發----require.js

前言

前端開發中,起初只要在script標籤中嵌入幾十上百行代碼就能實現一些基本的交互效果,後來js獲得重視,應用也普遍起來了,jQuery,Ajax,Node.Js,MVC,MVVM等的助力也使得前端開發獲得重視,也使得前端項目愈來愈複雜,然而,JavaScript卻沒有爲組織代碼提供任何明顯幫助,甚至沒有類的概念,更不用說模塊(module)了,因此,進行模塊化開發的重要性就不言而喻了。那麼什麼是模塊呢?前端

一個模塊就是實現特定功能的文件,有了模塊,咱們就能夠更方便地使用別人的代碼,想要什麼功能,就加載什麼模塊。node

因此,今天小編介紹一下js模塊化開發的幾種方法。jquery

 

1、模塊化開發規範

js模塊化的開發並非爲所欲爲的,爲了便於他人的使用和交流,須要遵循必定的規範。目前,通行的js模塊規範主要有兩種:CommonJSAMDajax

 

1.1AMD

AMD 即Asynchronous Module Definition,中文名是「異步模塊定義」的意思。它是一個在瀏覽器端模塊化開發的規範,服務器端的規範是CommonJS;api

模塊將被異步加載,模塊加載不影響後面語句的運行。全部依賴某些模塊的語句均放置在回調函數中。數組

關於AMD有兩個很是重要的概念,那就是用於模塊定義的define方法和用於處理依賴加載的require方法。瀏覽器

 

(1)做爲一個規範,只需定義其語法API,而不關心其實現。define函數定義以下:服務器

1 define(
2      [module-name?] /*可選*/, 
3      [array-of-dependencies?] /*可選*/, 
4      [module-factory-or-object]
5  );
其中:
  • module-name: 模塊標識,能夠省略。若是沒有這個屬性,則稱爲匿名模塊。
  • array-of-dependencies: 所依賴的模塊,能夠省略。
  • module-factory-or-object: 模塊的實現,或者一個JavaScript對象

舉個栗子:閉包

define(
    "myModule",
    ["foo", "bar"],

    // 模塊定義函數,依賴(foo,bar)做爲參數映射到函數上
    function (foo, bar) {
        // 建立模塊
        var myModule = {
            myFun: function () {
                console.log("Jeri");
            }
        }

        // 返回定義的模塊
        return myModule;
    }
);

 

(2)require()方法,有兩個參數:app

require([module], callback);

 

 其中:

  • 第一個參數[module],是一個數組,裏面的成員就是要加載的模塊;
  • 第二個參數callback,則是加載成功以後的回調函數。

 舉個實際栗子:

1 require(['math'], function (math) {
2     math.add(2, 3);
3   });

 

1.2CommonJS規範

 CommonJS是服務器端模塊的規範,根據CommonJS規範,一個單獨的文件就是一個模塊。每個模塊都是一個單獨的做用域,也就是說,在該模塊內部定義的變量,沒法被其餘模塊讀取,除非定義爲global對象的屬性。輸出模塊變量的最好方法是使用module.exports對象。

不過,與AMD表現形式不一樣的是,CommonJS模塊並不使用define進行定義。CommonJS模塊由兩部分組成:變量exports和require函數。

(1)exports/require:加載模塊使用require方法,該方法讀取一個文件並執行,最後返回文件內部的module.exports對象。

再舉個栗子:建立兩個js文件:

libJS:

1 // 新定義的模塊方法
2 function log(arg) {
3     console.log(arg);
4 }
5 
6 // 把方法暴露給其餘模塊
7 exports.log = log;

 

 app.JS:

 1 // ./lib是咱們須要的一個依賴
 2 var lib = requrie("./lib");
 3 
 4 // 新定義的模塊方法
 5 function foo() {
 6     lib.log("jeri");
 7 }
 8 
 9 // 把方法暴露給其餘模塊
10 exports.foo = foo;

 

(2)module.exports

直接舉栗子:

1 var i = 1;
2 var max = 30;
3 
4 module.exports = function () {
5   for (i -= 1; i++ < max; ) {
6     console.log(i);
7   }
8   max *= 1.1;
9 };

 

2、JS模塊的經常使用寫法

 在前言中小編也提過,模塊:就是一個模塊就是實現特定功能的文件,有了模塊,咱們就能夠更方便地使用別人的代碼,想要什麼功能,就加載什麼模塊。

除了接下來要講的require.js,還有適合於一些簡單模塊的幾種經常使用寫法。

 

2.1字面量寫法

要知道,模塊就是實現特定功能的一組方法。

只要把不一樣的函數(以及記錄狀態的變量)簡單地放在一塊兒,就算是一個模塊。這也是最簡單的一種寫法。也就是說,每個函數就是一個簡單的模塊。

1 function func1 (){
2   alert("這是func1");
3 };
4 function func2 (){
5   alert("這是func2");
6 }

 把栗子中的兩個函數func1()和func2()就組成了一個模塊;

不過,這種寫法有着必定的缺點:

若是隻是實現一些簡單的功能還好,若是實現複雜的功能,太多的函數就會出現問題,"污染"了全局變量,沒法保證不與其餘模塊發生變量名衝突,並且模塊成員之間看不出直接關係。

2.2對象寫法

 因此,爲了解決上述的問題,把模塊寫成一個對象,全部的模塊成員都放到這個對象裏面不失爲一個好的方式。

再再舉個栗子:

 1 var module = {
 2     func1 : function(){
 3       alert(1);      
 4     }
 5 
 6     func2 : function(){
 7       alert(2);      
 8     }
 9 }
10 
11 module.func1();
12 module.func2();

 

2.3經過閉包實現

 在JavaScript中,並不能能夠直接聲明類,但咱們可使用閉包來封裝私有的屬性和方法,進而模擬類的概念,在JavaScript中實現Module模式;

瘋狂的舉栗子:

 1 var myModule = (function () {
 2 
 3     // 私有變量
 4     var privateVar = 0;
 5 
 6     // 私有函數
 7     var privateFun = function (foo) {
 8         console.log(foo);
 9     };
10 
11     return {
12         // 私有變量
13         publicVar: "foo",
14 
15         // 公有函數
16         publicFun: function (arg) {
17 
18             // 修改私有變量
19             privateVar ++;
20 
21             // 傳入bar調用私有方法
22             privateFun(arg);
23         }
24     };
25 }) ()

 

2.4輸入全局變量

獨立性是模塊的重要特色,模塊內部最好不與程序的其餘部分直接交互。爲了在模塊內部調用全局變量,必須顯式地將其餘變量輸入模塊。

 

1 var module1 = (function ($, YAHOO) {
2     //...
3   })(jQuery, YAHOO);

 

3、require.js

 requir.JS本就是爲了實現js的模塊開發而建立的一個js腳本,其主要有着兩大優勢:

(1)實現js文件的異步加載,避免網頁失去響應;

(2)管理模塊之間的依賴性,便於代碼的編寫和維護。

 

3.1require.js的實現步驟

 (1)衆所周知,要導入js文件,爲了不網頁失去響應有兩種方法;

第一種,把<script></script>放在文件的最後。

今天,咱們主要說第二種:

 <script src="js/require.js" defer async="true" ></script>

 async屬性代表這個文件須要異步加載,避免網頁失去響應。可是,IE不支持這個屬性,只支持defer,因此須要把defer也寫上。

(2)在HTML中導入require.JS文件後,就能夠編寫本身的main.js文件。

首先,導入main.js文件:

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

 

其中:data-main屬性的做用是,指定網頁程序的主模塊。

在上例中,就是js目錄下面的main.js,這個文件會第一個被require.js加載。因爲require.js默認的文件後綴名是js,因此能夠把main.js簡寫成main。 

(3)編寫main.js;

1  require(['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC){
2     // some code here
3   });

 經過require方法,實現代碼的模塊加載,傳入兩個參數:

①第一個參數是一個數組,表示代碼所依賴的模塊。
②第二個參數是一個回調函數,當前面的模塊加載完成後,就會被調用。
加載的模塊一參數的形式傳入,從而在回調函數內部可使用這些模塊,回調函數就是整個頁面的JS代碼;

再次瘋狂的舉栗子:

1 require(['jquery', 'underscore', 'backbone'], function ($, _, Backbone){
2     // some code here
3   });

 

3.2模塊的加載

在上面的栗子中,咱們可使用require.config()方法,對模塊的加載行爲進行自定義。

(1)require.config()就寫在主模塊(main.js)的頭部。參數就是一個對象,這個對象的paths屬性指定各個模塊的加載路徑。 

 不要命的舉栗子:

1 require.config({
2     paths: {
3       "jquery": "jquery.min",
4       "underscore": "underscore.min",
5       "backbone": "backbone.min"
6     }
7   });

 

 (2)上面的代碼給出了三個模塊的文件名,路徑默認與main.js在同一個目錄(js子目錄)。

若是這些模塊在其餘目錄,好比js/lib目錄,則有兩種寫法。

一種是逐一指定路徑。

再次舉栗子:

1 require.config({
2     paths: {
3       "jquery": "lib/jquery.min",
4       "underscore": "lib/underscore.min",
5       "backbone": "lib/backbone.min"
6     }
7   });

 另外一種則是直接改變基目錄(baseUrl)。

再再次舉栗子:

 require.config({
    baseUrl: "js/lib",
    paths: {
      "jquery": "jquery.min",
      "underscore": "underscore.min",
      "backbone": "backbone.min"
    }
  });

 (3)若是某個模塊在另外一臺主機上,也能夠直接指定它的網址;

舉栗子:

require.config({
    paths: {
      "jquery": "https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min"
    }
  });

 

3.3require的AMD模塊寫法

require.js加載的模塊,採用AMD規範。也就是說,模塊必須按照AMD的規定來寫。

具體來講,就是模塊必須採用特定的define()函數來定義。若是一個模塊不依賴其餘模塊,那麼能夠直接定義在define()函數之中。

假定如今有一個math.js文件,它定義了一個math模塊。那麼,math.js就要這樣寫:

 1 // math.js
 2 
 3   define(function (){
 4 
 5     var add = function (x,y){
 6 
 7       return x+y;
 8 
 9     };
10 
11     return {
12 
13       add: add
14     };
15 
16   });

 

 

加載方法以下:

1 // main.js
2 
3   require(['math'], function (math){
4 
5     alert(math.add(1,1));
6 
7   });

 

 

若是這個模塊還依賴其餘模塊,那麼define()函數的第一個參數,必須是一個數組,指明該模塊的依賴性。

 1  define(['myLib'], function(myLib){
 2 
 3     function foo(){
 4 
 5       myLib.doSomething();
 6 
 7     }
 8 
 9     return {
10 
11       foo : foo
12 
13     };
14 
15   });

 

做者編

 在平常的工做中,js的模塊法開發是一個不可或缺的一部分。在這裏只是介紹了基於AMD模塊的require.js。還有基於commonJS規範的node.js。小編會在下次和你們一塊兒學習。

相關文章
相關標籤/搜索