模塊化

*解析

模塊是可以實(shí)現(xiàn)特定功能的一組代碼。

由于JS不能handle超大規(guī)模代碼,所以要借鑒其它語言處理這種問題的方式:
把邏輯相關(guān)的代碼組織到同一個(gè)區(qū)域,區(qū)域內(nèi)部相對(duì)獨(dú)立和外界互不干擾;
外部使用時(shí)直接引用對(duì)應(yīng)的區(qū)域即可。

模擬類似的功能,用來隔離、組織復(fù)雜的JavaScript代碼,我們稱為模塊化。

*作用

1 解決命名沖突
2 解決互相依賴
3 提高代碼的可讀性
4 提高代碼的復(fù)用性

*規(guī)范

**CommonJS

解析:
服務(wù)器端使用的模塊規(guī)范 例如 Node.js

使用:
1 定義模塊 一個(gè)文件 = 一個(gè)模塊 = 一個(gè)單獨(dú)的作用域
2 模塊輸出: 唯一出口module.exports對(duì)象,存放輸出內(nèi)容
3 加載模塊: 使用require方法讀取文件并執(zhí)行,返回ta內(nèi)部的module.exports對(duì)象

舉例:                      
  
Model-1.js                    1 定義模塊
    var name = 'jrg';           
    function a(){...}             name是模塊的內(nèi)部變量,只有文件內(nèi)的函數(shù)可以使用
    function b(){...}                            
    module.exports={          2 模塊輸出 (導(dǎo)出接口)
        a:a,
        b:b
    }

Model-2.js                        *新模塊 = 新文件
    function c(){...}
    module.exports = c


main.js                       3 加載模塊                              
    var xx = require('./Model-1');
    var dd = require('./Model-2');  使用哪個(gè)模塊再引入                        
    xx.a()                      
    dd.c()                          然后就可以調(diào)用模塊提供的方法

**問題

Q CommonJS 規(guī)范在服務(wù)器端這么方便,那么瀏覽器端可以用嗎?
A NO!
R 服務(wù)器端的文件在本地 => 同步加載;瀏覽器端的文件在遠(yuǎn)程服務(wù)器 =>異步加載
····所以CommonJS模塊在瀏覽器環(huán)境中無法正常加載。
····瀏覽器端需要另外的規(guī)范來封裝模塊 => AMD & CMD

**AMD

解析:
瀏覽器端使用的模塊規(guī)范之一 Asynchronous Module Definition異步模塊定義

define函數(shù),定義模塊-------------------------------------------------- 

語法: 
    define(id?, dependencies?, factory)

參數(shù):
    id:模塊名;如果沒有參數(shù),默認(rèn)為文件名。
    dependencies:一個(gè)數(shù)組;當(dāng)前模塊 [依賴的模塊名稱集合]。
    factory:工廠函數(shù);模塊初始化要執(zhí)行的函數(shù)(只執(zhí)行一次) or 對(duì)象(模塊的輸出值)。


 require函數(shù),加載模塊-------------------------------------------------

 語法:  require([dependencies], function(){});

 參數(shù):  [dependencies]是一個(gè)數(shù)組,表示所依賴的模塊;
         function(){} 是一個(gè)回調(diào)函數(shù),當(dāng)前面指定的模塊都加載成功后,以參數(shù)形式傳入該函數(shù),
                      然后函數(shù)內(nèi)部就可以使用這些模塊了。

 
 舉例----------------------------------------------------------------------------

 myModule1.js    定義模塊 
     define(['dependency'], function(){      
         function a(){...} // 使用面向?qū)ο蠓绞椒庋b好的組件
         return a,        //  留出接口
     });

 main.js      加載模塊  
     require(['myModule1','myModule2'], function (myModule1,myModule2){    
          myModule1.a();      // 調(diào)用組件
     });

**CMD

解析:
國內(nèi)發(fā)展出來的模塊規(guī)范Common Module Definition通用模塊定義

define函數(shù),定義模塊---------------------------------------------------------

語法:               
    define(function(require, exports, module){ });

參數(shù):    
   require 是一個(gè)方法,獲取其他模塊的接口
   exports 是一個(gè)對(duì)象,向外提供模塊接口
   module 是一個(gè)對(duì)象,存儲(chǔ)了一些屬性和方法

舉例--------------------------------------------------------------------------

 ModuleA.js     定義模塊 
   define(function(require, exports, module) {    function的三個(gè)參數(shù)固定不變 
     var a = require('a.js')                       函數(shù)內(nèi)部,用到誰就引入誰
     a();                                          寫法類似commonJS
     ModuleA.exprots = xx;
   });

main.js       加載模塊  
   seajs.use(['ModuleA.js'], function(ModuleA){ ... });

模塊化工具:
?由于不是JavaScript原生支持,
使用AMD需要用到對(duì)應(yīng)的庫函數(shù)RequireJS;
使用CMD需要用到對(duì)應(yīng)的庫函數(shù)SeaJS
其實(shí)AMDCMD分別 是RequireJSSeaJS 在推廣過程中對(duì)模塊定義的規(guī)范化產(chǎn)出;
同樣倡導(dǎo)模塊化開發(fā)理念,核心價(jià)值是讓 JavaScript 的模塊化開發(fā)變得簡單自然。

?AMDCMD的區(qū)別?
** 1** 關(guān)于依賴的模塊,加載都是異步,執(zhí)行處理不同
AMD:推崇依賴前置,提前執(zhí)行(依賴先執(zhí)行)
CMD:推崇依賴就近,延遲執(zhí)行(運(yùn)行到需加載,根據(jù)順序執(zhí)行)
** 2** 關(guān)于API
AMD:API根據(jù)使用范圍有區(qū)別,但使用同一個(gè)api接口
CMD:每個(gè)API的職責(zé)單一

**requireJS

?requireJS主要解決兩個(gè)問題:
1 實(shí)現(xiàn)js文件的異步加載,避免網(wǎng)頁失去響應(yīng);
2 管理模塊之間的依賴性,便于代碼的編寫和維護(hù)。

如果
   不使用`requireJS`就要單獨(dú)加載每個(gè)js文件,像這樣:
   <script src="1.js"></script>
   <script src="2.js"></script>
   <script src="3.js"></script>
 缺點(diǎn)
   1 加載的時(shí)候,瀏覽器會(huì)停止網(wǎng)頁渲染,加載文件越多,網(wǎng)頁失去響應(yīng)的時(shí)間就會(huì)越長;
   2 由于js文件之間存在依賴關(guān)系,因此必須嚴(yán)格保證加載順序,依賴性最大的模塊必須放到最后,
     當(dāng)依賴關(guān)系很復(fù)雜的時(shí)候,代碼的編寫和維護(hù)都會(huì)變得困難。

**總結(jié)

至此,已經(jīng)了解模塊規(guī)范,可以寫出符合規(guī)范的 模塊文件了!
以AMD為例,梳理一下使用過程:

1 下載require.js文件,放入根目錄
2 頁面引入requireJS庫<script src="http://require.js"></script> => 主文件
3 頁面引入主文件 <script src="http://main.js"></script> => 加載模塊
4 主文件 => 已放入根目錄的模塊文件
Tip:
主文件=>加載模塊=>require函數(shù)=>語法require([dependencies], function(){})
模塊文件=>定義模塊=>define函數(shù)=>語法define([dependencies], factory)

**r.js

這是一個(gè)打包工具

作用
把所有的模塊和框架js文件壓縮到同一個(gè)js文件里,
Before: 引入requireJS庫=>引入主文件=>查找模塊
After : 引入requireJS庫=>查找模塊

使用
1 下載r.js文件,放入根目錄
2 配置壓縮文件build.js
3 打開node,進(jìn)入目標(biāo)DEMO-AMD
4 執(zhí)行命令行node r.js -o build.js,會(huì)自動(dòng)生成壓縮文件
5 將頁面上的主文件地址main.js替換為壓縮后的文件index.merge.min.js

*應(yīng)用

Demo

▼DEMO-AMD   
   ?index.html   
   ?CSS              
   ▼JS
     ▼lib            框架&庫目錄
       ?require.js
       ?r.js
       ?jquery.js
        ......
     ▼app            組件目錄
       ?gotop.js
        ......
     ?main.js       主文件
     ?build.js      壓縮配置文件

     ▼dist          輸出目錄
       ?index.merge.min.js   


   ■ index.html
    頁面加載 <script src="http://js/lib/require.js" data-main="js/main.js"></script>
    □ src       先加載庫 => 執(zhí)行require.js => 解析后指向主文件  
    □ data-main 自定義屬性 => 執(zhí)行main.js  =>  主文件里是所有模塊的入口


   ■ main.js                主文件 =>
     requirejs.config({              □ 配置路徑,方便查找
         baseUrl: "./js/app",             默認(rèn)文件夾(加載時(shí)寫直接寫里面的模塊名)
         paths: {                         特殊文件/夾(相對(duì)于baseUrl)
             'jquery': '../lib/jquery'        指向模塊  (加載時(shí)寫模塊名)
             'lib':'../lib'                   指向文件夾(加載時(shí)寫lib下模塊名)
         }                                  
     });
     requirejs(["GoTop","lib/xx",...],
     function(GoTop,$,...) {         □ 加載([依賴模塊],工廠函數(shù))
         new GoTop();                          模塊加載完畢,作為參數(shù)傳入工廠函數(shù)
         ......                                 執(zhí)行工廠函數(shù)
     });

    ● 這里的baseUrl是main.js相對(duì)于index.html=> 從index出發(fā)找到app
    ● requirejs(["xxx"]) => 如果沒有工廠函數(shù),直接加載并執(zhí)行文件


   ■ build.js             壓縮配置文件 =>  
     ({                                □ 配置路徑   
         baseUrl: ".",                       兩個(gè)baseUrl指向要保持一致(都指向app)  
         paths: {
             'jquery': './lib/jquery',
             'GoTop':'./com/GoTop',
             ......
         },
         name: "main",                       配置入口
         out: "./dist/index.merge.min.js"    配置出口(自定義)
     });

    ● 這里的baseUrl是build.js相對(duì)于自身的,=> 從build 出發(fā)找到 app

參考 詳解JavaScript模塊化開發(fā)

但是!程序員永遠(yuǎn)有更便捷的方法 => webpack

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 什么是模塊化開發(fā)? 前端開發(fā)中,起初只要在script標(biāo)簽中嵌入幾十上百行代碼就能實(shí)現(xiàn)一些基本的交互效果,后來js...
    半世韶華憶闌珊閱讀 719評(píng)論 0 0
  • 原文鏈接:http://www.cnblogs.com/lvdabao/p/js-modules-develop....
    舌尖上的大胖閱讀 839評(píng)論 0 1
  • 在JavaScript發(fā)展初期就是為了實(shí)現(xiàn)簡單的頁面交互邏輯,寥寥數(shù)語即可;如今CPU、瀏覽器性能得到了極大的提升...
    簡不簡單_都好閱讀 258評(píng)論 0 0
  • 前端模塊化 在JavaScript發(fā)展初期就是為了實(shí)現(xiàn)簡單的頁面交互邏輯,寥寥數(shù)語即可;如今CPU、瀏覽器性能得到...
    景岳閱讀 278評(píng)論 2 4
  • 楚漢之爭中豪杰并出,有勇之人有謀之人紛紛投靠兩位爭執(zhí)不休的楚王與漢王,而韓信便在這場戰(zhàn)爭中問事了,他效忠于劉邦,創(chuàng)...
    無端若夢閱讀 601評(píng)論 0 0

友情鏈接更多精彩內(nèi)容