web前端-深入(4)-AMD_CMD_RequireJS

題目1: 為什么要使用模塊化?

  • 解決命名沖突
  • 依賴管理
  • 提高代碼可讀性
  • 代碼解耦,提高復(fù)用性

題目2: CMD、AMD、CommonJS 規(guī)范分別指什么?有哪些應(yīng)用

  1. CommonJS

1、CommonJS 是用于服務(wù)器端模塊的規(guī)范。Node.js采用了這個規(guī)范。Node.JS首先采用了js模塊化的概念。
2、定義模塊:根據(jù)CommonJS規(guī)范,一個單獨(dú)的文件就是一個模塊。每一個模塊都是一個單獨(dú)的作用域,也就是說,在該模塊內(nèi)部定義的變量,無法被其他模塊讀取,除非定義為global對象的屬性。
3、模塊輸出:模塊只有一個出口,module.exports對象,我們需要把模塊希望輸出的內(nèi)容放入該對象。
4、加載模塊: 加載模塊使用require方法,該方法讀取一個文件并執(zhí)行,返回文件內(nèi)部的module.exports對象。

//模塊定義 myModel.js
var name = 'Byron';
function printName(){
    console.log(name);
}
function printFullName(firstName){
    console.log(firstName + name);
}
module.exports = {                //module.exports對象是作為模塊出口,方便其他的js調(diào)用
    printName: printName,
    printFullName: printFullName
}

//加載模塊
var nameModule = require('./myModel.js');       //相當(dāng)于nameModule調(diào)用了JS的require函數(shù),文件擴(kuò)展名可省略,該方法讀取一個文件并執(zhí)行,返回內(nèi)部的module.exports對象。
nameModule.printName();
//用法:將模塊定義和加載模塊代碼分別放在兩個js文件中(a.js,b.js),然后在bash中執(zhí)行代碼node b.js,結(jié)果會在bash中顯示 

缺點(diǎn):
1、require("./myModel.js")里的路徑很不好處理
2、當(dāng)執(zhí)行require("./myModel.js")時,瀏覽器要先下載文件,由于是同步運(yùn)行,所以要等到文件下載完成時才能執(zhí)行,但是CommonJS只支持服務(wù)器端運(yùn)行,不支持瀏覽器運(yùn)行

  1. AMD

1、AMD是"Asynchronous Module Definition"的縮寫,意思就是"異步模塊定義"。
2、它采用異步方式加載模塊,模塊的加載不影響它后面語句的運(yùn)行。
3、所有依賴這個模塊的語句,都定義在一個回調(diào)函數(shù)中,等到加載完成之后,這個回調(diào)函數(shù)才會運(yùn)行。
4、由于不是JavaScript原生支持,使用AMD規(guī)范進(jìn)行頁面開發(fā)需要用到對應(yīng)的庫函數(shù),也就是RequireJS,實(shí)際上AMD 是 RequireJS 在推廣過程中對模塊定義的規(guī)范化的產(chǎn)出
5、requireJS主要解決兩個問題:1. 多個js文件可能有依賴關(guān)系,被依賴的文件需要早于依賴它的文件加載到瀏覽器。2. js加載的時候?yàn)g覽器會停止頁面渲染,加載文件越多,頁面失去響應(yīng)時間越長。

//格式:

//定義模塊:
define(id?, dependencies?, factory);    //?表示可選
//id:可選參數(shù),用來定義模塊的標(biāo)識,若沒有提供,默認(rèn)為腳本文件名(去掉拓展名)
//dependencies:是一個當(dāng)前模塊依賴的模塊名稱數(shù)組,默認(rèn)為["require", "exports", "module"],若factory的參數(shù)小于3,加載器會選擇參數(shù)個數(shù)調(diào)用工廠方法。
//factory:工廠方法,模塊初始化要執(zhí)行的函數(shù)或?qū)ο蟆H魹楹瘮?shù),只被執(zhí)行一次。若為對象,應(yīng)該為模塊的輸出值

//在頁面上使用require函數(shù)加載模塊:
require([dependencies], function(){});
//第一個參數(shù)是數(shù)組,表示所依賴的模塊
//第二個參數(shù)是回調(diào)函數(shù),當(dāng)前面的模塊都加載成功后將被調(diào)用。加載的模塊會以參數(shù)形式傳入該函數(shù),從而在回調(diào)函數(shù)內(nèi)部就可以使用這些模塊
//require()函數(shù)在加載依賴模塊時是異步加載的,這樣瀏覽器不會失去響應(yīng),它的回調(diào)函數(shù)只有模塊都加載成功后才運(yùn)行,解決了依賴性的問題。

//例如:
 require(['math'], function (math) {
    math.add(2, 3);
  });
  1. CMD

1、CMD(Common Module Definition) 通用模塊定義。該規(guī)范明確了模塊的基本書寫格式和基本交互規(guī)則。該規(guī)范是在國內(nèi)發(fā)展出來的。AMD是依賴關(guān)系前置,CMD是按需加載。
2、就像AMD有個requireJS,CMD有個瀏覽器的實(shí)現(xiàn)SeaJS,SeaJS要解決的問題和requireJS一樣,只不過Sea.js 推崇一個模塊一個文件,遵循統(tǒng)一的寫法

//定義模塊
     define(id?, deps?, factory)
//CMD推崇一個文件一個模塊,所以經(jīng)常就用文件名作為模塊id,一般不寫
//CMD推崇依賴就近,所以一般不在define的參數(shù)中寫依賴,在factory中寫,所以deps參數(shù)省略
//factory: function(require, exports, module){},require 是一個方法,接受模塊標(biāo)識作為唯一參數(shù),用來獲取其他模塊提供的接口。exports 是一個對象,用來向外提供模塊接口。module 是一個對象,上面存儲了與當(dāng)前模塊相關(guān)聯(lián)的一些屬性和方法。

//加載模塊
seajs.use(['myModule.js'], function(my){

});

//例如:

// 定義模塊  myModule.js
define(function(require, exports, module) {
  var $ = require('jquery.js')
  exports.add=function(){
    $('div').addClass('active');
  }
});

// 加載模塊
seajs.use(['myModule.js'], function(my){
  my.add();
});

題目3: 使用 requirejs 完善入門任務(wù)15,包括如下功能:

 1. 首屏大圖為全屏輪播
 2. 有回到頂部功能
 3. 圖片區(qū)使用瀑布流布局(圖片高度不一),下部有加載更多按鈕,點(diǎn)擊加載更多會加載更多數(shù)據(jù)(數(shù)據(jù)在后端 mock)

代碼
預(yù)覽

筆記

1、CommonJS
//實(shí)際使用情況:

//math.js
exports.add = function() {
    var sum = 0, i = 0, args = arguments, l = args.length;
    while (i < l) {
        sum += args[i++];
    }
    return sum;
};
//increment.js
var add = require('math').add;
exports.increment = function(val) {
    return add(val, 1);
};
//program.js
var inc = require('increment').increment;
var a = 1;
inc(a); 
// 2
2、AMD(Require.js)
//實(shí)際使用案例:

// 定義模塊 myModule.js
define(['dependency'], function(){
    var name = 'Byron';
    function printName(){
        console.log(name);
    }

    return {
        printName: printName
    };
});

// 加載模塊
require(['myModule'], function (my){
  my.printName(); });
3、CMD(Sea.js)
//實(shí)際使用情況

// 定義模塊  myModule.js
define(function(require, exports, module) {
  var $ = require('jquery.js')
  $('div').addClass('active');
});

// 加載模塊
seajs.use(['myModule.js'], function(my){

});
//demo
//math.js
define(function(require, exports, module) {
  exports.add = function() {
    var sum = 0, i = 0, args = arguments, l = args.length;
    while (i < l) {
      sum += args[i++];
    }
    return sum;
  };
});
//increment.js
define(function(require, exports, module) {
  var add = require('math').add;
  exports.increment = function(val) {
    return add(val, 1);
  };
});
//program.js
define(function(require, exports, module) {
  var inc = require('increment').increment;
  var a = 1;
  inc(a); // 2

  module.id == "program";
});
4、AMD與CMD區(qū)別
  1. 最明顯的區(qū)別就是在模塊定義時對依賴的處理不同
    1、AMD推崇依賴前置,在定義模塊的時候就要聲明其依賴的模塊
    2、CMD推崇就近依賴,只有在用到某個模塊的時候再去require
    3、同樣都是異步加載模塊,AMD在加載模塊完成后就會執(zhí)行該模塊,所有模塊都加載執(zhí)行完后會進(jìn)入require的回調(diào)函數(shù),執(zhí)行主邏輯,這樣的效果就是依賴模塊的執(zhí)行順序和書寫順序不一定一致,看網(wǎng)絡(luò)速度,哪個先下載下來,哪個先執(zhí)行,但是主邏輯一定在所有依賴加載完成后才執(zhí)行
    4、CMD加載完某個依賴模塊后并不執(zhí)行,只是下載而已,在所有依賴模塊加載完成后進(jìn)入主邏輯,遇到require語句的時候才執(zhí)行對應(yīng)的模塊,這樣模塊的執(zhí)行順序和書寫順序是完全一致的
5、requirejs使用步驟

目的: 是代碼的模塊化,它使用了不同于傳統(tǒng)<script>標(biāo)簽的腳本加載步驟。可以用它來加速代碼加載、優(yōu)化代碼,但其主要目的還是為了代碼的模塊化。

  1. 加載js文件:
<script data-main="scripts/main.js" src="scripts/require.js"></script>
//data-main屬性中的main.js文件,requirejs使用它來啟用腳本加載過程,當(dāng)頁面加載了requirejs,立即執(zhí)行main.js文件
//設(shè)置了data-main,baseUrl指向scripts目錄,也可用requirejs.config({})手動配置(當(dāng)前目錄為html所在目錄,所以要以html所在目錄做為基準(zhǔn)),若兩者都沒,baseUrl默認(rèn)指向引用requirejs的html所在的目錄。
  1. 設(shè)置main.js文件
//這是目錄表
www/
    -index.html
    -js/
    ---app/
    ------sub.js
    ---lib/
    ------jquery.js
    ------canvas.js
    ---main.js
//main.js
 requirejs.config({
    baseUrl: 'js/lib', 
    paths: {
        app: '../app'
    }
    });
    //加載模塊
    requirejs(['jquery', 'canvas', 'app/sub'],
        function   ($, canvas, sub) {
          //jquery,canvas,sub 資源都已經(jīng)加載完畢,可以用了。
    }); 
  });
//baseUrl為加載文件的起始位置,不過請注意的是paths配置(paths是路徑相對于baseUrl而言的,加載的文件都不需要.js后綴。
//想要避開baseUrl+paths(Module ID)的解析過程,直接指定加載當(dāng)前HTML頁面目錄下的腳本三種方法:
//腳本以".js"結(jié)束
//以"/"開始
//包含URL協(xié)議,如http:或https:
//canvas.js
define(['app/sub'], function(){
    var name = 'Byron';
    function printName(){
        console.log(name);
    }
    return {
        printName: printName    //這是給其他模塊的接口
    };
});
//sub.js
define(["canvas"],function(Canvas){
  Canvas.printName();            //依賴canvas模塊,并且引用模塊功能
});

(mission 4)

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

推薦閱讀更多精彩內(nèi)容