require.js(初篇)

一、關于模塊化編程

1.1傳統代碼的缺陷

隨著網站功能逐漸豐富,網頁中的js也變得越來越復雜和臃腫。

原有通過script標簽來導入一個個的js文件這種方式已經不能滿足現在互聯網開發模式,并且這樣寫有很大的 缺點,

首先,加載的時候,瀏覽器會停止網頁的渲染,加載的文件越多,那么網頁失去響應的時間越長,

其次,由于js文件之間存在依賴關系,因此必須嚴格保證加載順序,依賴性大的模塊一定要放在最后加載,當依賴關系很復雜的時候,代碼的編寫和維護都會非常困難。

所以我們需要團隊協作、模塊復用、單元測試等等一系列復雜的需求。

二、什么是模塊化及模塊化編程規范

模塊化是只在處理某些問題的時候,按照一種分類思想對功能進行模塊化的管理和使用。

2.1 require.js的誕生

require.js的誕生就是為了解決上述<script>加載問題。

AMD

require.js加載的模塊,采用AMD規范。也就是說,模塊必須按照AMD的規定來寫。即需要用define()來定義模塊和require(),后續會介紹如何定義模塊

對于模塊化的發展暫不做詳細介紹,百度很6的~

2.2require.js的的加載

先去官網下載最新版本,下載后,可以選擇把它放在文件的根目錄下或者是js文件下
<script type="text/javascript" src="js/require.js" ></script>

為了避免加載文件的時候造成網頁失去響應。解決辦法有倆個,一個是把文件的加載放在網頁的最底部,一個是寫成下面這樣
<script src="js/require.js" async="async" ></script>
async屬性表明這個文件需要異步加載,避免網頁加載的時候失去響應。

加載require.js之后,需要加載我們自己的js文件代碼,假設我們自己的代碼文件是app.js,也放在根目錄下,那么就寫成下面這樣
<script type="text/javascript" src="js/require.js" data-main="app"></script>
data-main這個屬性的作用是指定我們網頁程序的主模塊。這個文件會第一個被require.js加載。由于require.js默認的文件后綴名是js,所以可以把app.js簡寫成app。

2.3 主模塊的寫法

一旦我們定義了主模塊的js文件,意思這個就是整個網頁的入口代碼,所有的代碼都從這開始運行。

如果主模塊代碼不依賴于其他任何模塊,那么可以直接寫JavaScript代碼。

這樣就失去了require.js的意義了,因為正常情況下,主模塊都會依賴于其他模塊,這時就需要遵守AMD規范。

看栗子,格式像這樣

      // app.js
      require(['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC){
       .......
      });

require()函數
require()函數接受兩個參數。
第一個參數是一個數組,表示程序所依賴的模塊,即主模塊依賴['moduleA', 'moduleB', 'moduleC']這三個模塊;
第二個參數是一個回調函數,當前面指定的模塊都加載成功后,它將被調用。加載的模塊要以參數形式傳入回調函數,從而在回調函數內部就可以使用這些模塊。

舉個栗子

require(["a","b","c"],function(A,B,C){
      .....something.....
})

此時各個模塊之間的關系是這樣的,index.html和app.js和modules文件架 在根目錄下,modules文件下有moduleA,moduleB,moduleC三個文件夾,里邊分別有a.js 和 b.js 和 c.js。

捕獲.PNG

require.js會先加載'a', 'b', 'c',然后再運行回調函數。主模塊的代碼就寫在回調函數中。

2.4模塊的加載

上一節的栗子中,主模塊的依賴模塊是'a', 'b', 'c'
文件名分別為a.js ,b.js ,c.js 然后自動加載

使用require.config()方法,我們可以對模塊的加載行為進行自定義。require.config()就寫在主模塊(app.js)的頭部。參數就是一個對象,這個對象的paths屬性指定各個模塊的加載路徑。

栗子

//通過require.config方法來配置要導入的模塊路徑
require.config({
    paths:{
        //這里寫要導入的路徑和對應生成的模塊名字
        a:"modules/moduleA/a",
        b:"modules/moduleB/b",
        c:"modules/moduleC/c"
    }
})

另注
1.如果模塊在另一臺主機上,也可以直接指定它的網址。
2.如果在這文件在同在其他弄一個文件夾內,比如都在lib文件架內,也可以指定baseUrl

2.5 AMD定義模塊

AMD模塊必須采用define()函數來定義

1.如果一個模塊不依賴于其他模塊,那么可以直接定義在define()函數中。

假設上栗中的a.js模塊不依賴于其他模塊,那么a.js中的代碼如下

//define定義模塊(不依賴于任何其他模塊)
define(function () {
    //加法運算
    function add (x, y) {
        return x + y;
    }
    
    return {
        add : add
    }
})

2.定義模塊的時候如果有依賴于其他模塊的話,我們就可以把第一個參數加入,第一個參數是一個數組,數組中就是依賴模塊的名字或者路徑。

如果這里寫路徑,注意是相對于app.js而言的路徑

假設上栗中的b.js是依賴于jquery和a.js模塊的,那么我們可以在第一個參數中引入,代碼如下

//定義模塊的時候如果有依賴于其他模塊的話,我們就可以把第一個參數加入
//第一個參數是一個數組,數組中就是依賴模塊的名字或者路徑
//如果這里寫路徑需要注意是相對于app.js而言的路徑
define(['jquery', './modules/moduleA/a'], function ($, A) {
    //改變div顏色
    function changeColor () {
        $("#box").css({
                       //將div的北京變成藍色
            backgroundColor : "red"
        });
    }
    
    //私有方法(說白了就是給自己用,不支持導出這個功能)
    //計算兩數之差
    function mul (x, y) {
        return x - y;
    }
    
    function addAndMul (x, y) {
       //調用自身的兩個函數
        changeColor();
        //用到了A模塊里的功能和自身模塊的私有方法
        return A.add(x, y) + mul(x, y);
    }
    //因為后續數據需要反饋,所以一定要return
    return {
        addAndMul : addAndMul
    }
    
});

當require()函數加載上面這個模塊的時候,就會先加載他所依賴的模塊。

3.為了方便理解下面內容,我們在c.js中也定義一個模塊,其代碼如下

define(['a', 'b'], function (A, B) {
    function changeColor () {
        $("#box").css({
            //將div的背景變成藍色
            backgroundColor : 'blue'
        });
    }
    
    function fn (x, y) {
        changeColor();
        return  A.add(x, y) + B.addAndMul(x, y);
    }
    //因為后續數據需要反饋,所以一定要return
    return {
        fn : fn
    }
});

2.6 模塊的調用

此時我們定義了了三個模塊。分別為a.js 和b.js 和 c.js,并在主模塊app.js中引入了三個模塊。

此時我們需要調用這三個模塊,并發揮他們的功能,因此,在app.js中,我么除了引入三個模塊的路徑,還需要調用,代碼如下

//通過require方法來導入模塊
//如果上面配置了路徑,數組里導入的時候直接就可以寫上面路徑對應的模塊名字即可
//jquery比較特殊,叫jquery以外其他名字的話,導出模塊會是undefined
//注意:模塊支持導出的話,一定要對應上,不支持導出的模塊,我們放在數組中的最后
require(['jquery', 'a', 'b', './modules/moduleC/c'], function (j, A, B, C) {
    console.log($);
    console.log(j);
    //使用A模塊的功能
    console.log(A.add(1, 2));
    //使用B模塊的功能
    console.log(B.addAndMul(1, 2));
    //使用C模塊的功能
    console.log(C.fn(1, 2));
});

調用了app.js需要依賴的a,b,c三個模塊,又進行了引用,那么此時app.js中的全部代碼如下

//通過require.config方法來配置要導入的模塊路徑
require.config({
    paths : {
        //這里寫要導入的路徑和對應生成的模塊名字
        jquery : './lib/jquery',
        a : './modules/moduleA/a',
        b : './modules/moduleB/b'
    }
})

//通過require方法來導入模塊
//如果上面配置了路徑,數組里導入的時候直接就可以寫上面路徑對應的模塊名字即可
//注意:模塊支持導出的話,一定要對應上,不支持導出的模塊,我們放在數組中的最后
require(['jquery', 'a', 'b', 'modules/moduleC/c'], function (j, A, B, C) {
    //使用A模塊的功能
    console.log(A.add(1, 2));
    //使用B模塊的功能
    console.log(B.addAndMul(1, 2));
    //使用C模塊的功能
    console.log(C.fn(1, 2));
});

注意代碼中c模塊的變化了么?你再仔細瞅瞅?說好的引用呢?
溫馨提示,也要注意b和c里面的代碼哦

如果在配置依賴的模塊路徑沒有配置,那么在require調用的時候,在數組參數中寫其路徑也是可以的。

主頁面index.html中沒有實際的內容,只是引用,代碼如下

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title></title>
        <style type="text/css">
            #box{
                width: 200px;
                height: 200px;
                background-color: pink;
            }
        </style>
    </head>
    <body>
        <div id="box"></div>
        <!-- 導入requireJS庫 -->
        <!-- data-main可以導入主入口文件app是指app.js -->
        <script type="text/javascript" src="lib/require.js" data-main="app"></script>
    </body>
</html>

此時運行index.html ** 注意 div的顏色。。**

運行結果(1).jpg

你覺得對么?按照加載的順序,應該最后加載c.js div的顏色怎么是紅色的?應該是藍色的才對?

因為我們在c.js中return的時候,又調用了b.js,所以最后又加載了b.js,所以,div變成了紅色~那么,如何解決這個問題呢?用變量存起來不就好啦 -,c.js中的代碼如下

define(['a', 'b'], function (A, B) {
    function changeColor () {
        $("#box").css({
            backgroundColor : 'blue'
        });
    }
    
    function fn (x, y) {
        var num = A.add(x, y) + B.addAndMul(x, y);
        changeColor();
        return num;
    }
    
    return {
        fn : fn
    }
});
此時我們再輸出一下結果
運行結果(2).jpg

此篇文章助大家理解require.js,真正的require.js用法,可沒這么簡單呢

不要吝嗇贊美,喜歡就點贊啦

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • requirejs是一個JavaScript文件和模塊加載器。requireJS允許你把你的javascript代...
    GQ1994閱讀 2,217評論 0 58
  • 本文參照阮老師的文章。一、為什么要用require.js?最早的時候,所有Javascript代碼都寫在一個文件里...
    索哥來了閱讀 298評論 0 3
  • JS中的模塊規范(CommonJS,AMD,CMD),如果你聽過js模塊化這個東西,那么你就應該聽過或Common...
    小蝦米前端閱讀 4,417評論 0 12
  • 【20171107星期二】 “你要相信凡事皆有因果,面對挑戰才能有好事降臨。” 很巧,上面這句話是在18:22分的...
    Lan寶石的練習室閱讀 341評論 0 0
  • 在小學時的我,老是跟一群朋友出去玩,一起吸煙,一起喝酒,一起以大欺小 ,一起上網吧,一起玩電子,贏錢的時候還是開心...
    I喜你耶閱讀 404評論 1 3