摘要:規(guī)范則是非同步加載模塊,允許指定回調(diào)函數(shù),可以實(shí)現(xiàn)異步加載依賴模塊,并且會提前加載由于主要用于服務(wù)器編程,模塊文件一般都已經(jīng)存在于本地硬盤,所以加載起來比較快,不用考慮非同步加載的方式,所以規(guī)范比較適用。
JS模塊化 模塊化的理解
什么是模塊?
將一個復(fù)雜的程序依據(jù)一定的規(guī)則(規(guī)范)封裝成幾個塊(文件), 并進(jìn)行組合在一起;
塊的內(nèi)部數(shù)據(jù)/實(shí)現(xiàn)是私有的, 只是向外部暴露一些接口(方法)與外部其它模塊通信;
一個模塊的組成
數(shù)據(jù)--->內(nèi)部的屬性;
操作數(shù)據(jù)的行為--->內(nèi)部的函數(shù);
模塊化是指解決一個復(fù)雜的問題時自頂向下把系統(tǒng)劃分成若干模塊的過程,有多種屬性,分別反映其內(nèi)部特性;
模塊化編碼:編碼時是按照模塊一個一個編碼的, 整個項(xiàng)目就是一個模塊化的項(xiàng)目;
非模塊化的問題頁面加載多個js的問題:
發(fā)生問題:
難以維護(hù) ;
依賴模糊;
請求過多;
所以,這些問題可以通過現(xiàn)代模塊化編碼和項(xiàng)目構(gòu)建來解決;
模塊化的優(yōu)點(diǎn)更好地分離:避免一個頁面中放置多個script標(biāo)簽,而只需加載一個需要的整體模塊即可,這樣對于HTML和JavaScript分離很有好處;
更好的代碼組織方式:有利于后期更好的維護(hù)代碼;
按需加載:提高使用性能,和下載速度,按需求加載需要的模塊
避免命名沖突:JavaScript本身是沒有命名空間,經(jīng)常會有命名沖突,模塊化就能使模塊內(nèi)的任何形式的命名都不會再和其他模塊有沖突。
更好的依賴處理:使用模塊化,只需要在模塊內(nèi)部申明好依賴的就行,增加刪除都直接修改模塊即可,在調(diào)用的時候也不用管該模塊依賴了哪些其他模塊。
模塊化的發(fā)展歷程 原始寫法只是把不同的函數(shù)簡單地放在一起,就算一個模塊;
function fun1(){ //... } function fun2(){ //... } //上面的函數(shù)fun1,fun2組成了一個模塊,使用的時候直接調(diào)用某個函數(shù)就行了。
缺點(diǎn):
"污染"了全局變量,無法保證不與其他模塊發(fā)生變量名沖突;
模塊成員之間看不出直接關(guān)系。
對象寫法為了解決污染全局變量的問題,可以把模塊寫成一個對象,所有的模塊成員都放到這個對象里面。
var module1 = new Object({ count : 0, fun1 : function (){ //... }, fun2 : function (){ //... } }); //這個里面的fun1和fun2都封裝在一個賭俠寧里,可以通過對象.方法的形式進(jìn)行調(diào)用; module1.fun1();
優(yōu)點(diǎn):
減少了全局上的變量數(shù)目;
缺點(diǎn):
本質(zhì)是對象,而這個對象會暴露所有模塊成員,內(nèi)部狀態(tài)可以被外部改寫。
立即執(zhí)行函數(shù)(IIFE模式)避免暴露私有成員,所以使用立即執(zhí)行函數(shù)(自調(diào)函數(shù),IIFE);
作用: 數(shù)據(jù)是私有的, 外部只能通過暴露的方法操作
var module1 = (function(){ var count = 0; var fun1 = function(){ //... } var fun2 = function(){ //... } //將想要暴露的內(nèi)容放置到一個對象中,通過return返回到全局作用域。 return{ fun1:fun1, fun2:fun2 } })() //這樣的話只能在全局作用域中讀到fun1和fun2,但是讀不到變量count,也修改不了了。 //問題:當(dāng)前這個模塊依賴另一個模塊怎么辦?IIFE的增強(qiáng)(引入依賴)
如果一個模塊很大,必須分成幾個部分,或者一個模塊需要繼承另一個模塊,這時就有必要采用"增強(qiáng)模式";
IIFE模式增強(qiáng):引入依賴;
這就是現(xiàn)代模塊實(shí)現(xiàn)的基石;
var module1 = (function (mod){ mod.fun3 = function () { //... }; return mod; })(module1); //為module1模塊添加了一個新方法fun3(),然后返回新的module1模塊。 //引入jquery到項(xiàng)目中; var Module = (function($){ var _$body = $("body"); // we can use jQuery now! var foo = function(){ console.log(_$body); // 特權(quán)方法 } // Revelation Pattern return { foo: foo } })(jQuery) Module.foo();js模塊化需要解決那些問題:
1.如何安全的包裝一個模塊的代碼?(不污染模塊外的任何代碼)
2.如何唯一標(biāo)識一個模塊?
3.如何優(yōu)雅的把模塊的API暴漏出去?(不能增加全局變量)
4.如何方便的使用所依賴的模塊?
模塊化規(guī)范Node: 服務(wù)器端
Browserify : 瀏覽器端
CommonJS:服務(wù)器端
概述
Node 應(yīng)用由模塊組成,采用 CommonJS 模塊規(guī)范。
CommonJS規(guī)范規(guī)定,每個模塊內(nèi)部,module變量代表當(dāng)前模塊。這個變量是一個對象,它的exports屬性(即module.exports)是對外的接口。加載某個模塊,其實(shí)是加載該模塊的module.exports屬性。
特點(diǎn)
所有代碼都運(yùn)行在模塊作用域,不會污染全局作用域。
模塊可以多次加載,但是只會在第一次加載時運(yùn)行一次,然后運(yùn)行結(jié)果就被緩存了,以后再加載,就直接讀取緩存結(jié)果。要想讓模塊再次運(yùn)行,必須清除緩存。
模塊加載的順序,按照其在代碼中出現(xiàn)的順序。
基本語法:
定義暴露模塊 : exports
exports.xxx = value // 通過module.exports指定暴露的對象value module.exports = value
引入模塊 : require
var module = require("模塊相對路徑")
引入模塊發(fā)生在什么時候?
Node:運(yùn)行時, 動態(tài)同步引入;
Browserify:在運(yùn)行前對模塊進(jìn)行編譯/轉(zhuǎn)譯/打包的處理(已經(jīng)將依賴的模塊包含進(jìn)來了), 運(yùn)行的是打包生成的js, 運(yùn)行時不需要再從遠(yuǎn)程引入依賴模塊;
CommonJS通用的模塊規(guī)范(同步)Node內(nèi)部提供一個Module構(gòu)建函數(shù)。所有模塊都是Module的實(shí)例。
每個模塊內(nèi)部,都有一個module對象,代表當(dāng)前模塊。
module.exports屬性表示當(dāng)前模塊對外輸出的接口,其他文件加載該模塊,實(shí)際上就是讀取module.exports變量。
Node為每個模塊提供一個exports變量,指向module.exports。
如果一個模塊的對外接口,就是一個單一的值,不能使用exports輸出,只能使用module.exports輸出。
Modules/1.0規(guī)范包含內(nèi)容:
模塊的標(biāo)識應(yīng)遵循的規(guī)則(書寫規(guī)范)
定義全局函數(shù)require,通過傳入模塊標(biāo)識來引入其他模塊,執(zhí)行的結(jié)果即為模塊暴露出來的API;
如果被require函數(shù)引入的模塊中也包含依賴,那么依次加載這些依賴;
如果引入模塊失敗,那么require函數(shù)應(yīng)該報(bào)一個異常;
模塊通過變量exports來向外暴露API,exports賦值暴露的只能是一個對象exports = {Obj},暴露的API須作為此對象的屬性。exports本質(zhì)是引入了module.exports的對象。不能直接將exports變量指向一個值,因?yàn)檫@樣等于切斷了exports與module.exports的聯(lián)系。
如果暴露的不是變量exports,而是module.exports。module變量代表當(dāng)前模塊,這個變量是一個對象,它的exports屬性(即module.exports)是對外的接口。加載某個模塊,其實(shí)是加載該模塊的module.exports屬性。exports=module.exports={Obj}
1.安裝node.js;
2.創(chuàng)建項(xiàng)目結(jié)構(gòu)
//結(jié)構(gòu)如下 |-modules |-module1.js//待引入模塊1 |-module2.js//待引入模塊2 |-module3.js//待引入模塊3 |-app.js//主模塊 |-package.json { "name": "commonjsnode", "version": "1.0.0" }
3.下載第三方模塊:舉例express
npm i express --save
4.模塊化編碼
// module1 // 使用module.exports = value向外暴露一個對象 module.exports = { name: "this is module1", foo(){ console.log("module1 foo()"); } } // module2 // 使用module.exports = value向外暴露一個函數(shù) module.exports = function () { console.log("module2()"); } // module3 // 使用exports.xxx = value向外暴露一個對象 exports.foo = function () { console.log("module3 foo()"); }; exports.bar = function () { console.log("module3 bar()"); }; exports.name = "this is module3" //app.js文件 var uniq = require("uniq"); //引用模塊 let module1 = require("./modules/module1"); let module2 = require("./modules/module2"); let module3 = require("./modules/module3"); //使用模塊 module1.foo(); module2(); module3.foo(); module3.bar(); module3.name;
5.通過node運(yùn)行app.js
命令:node.app.js
工具:右鍵-->運(yùn)行
借助Browserify
步驟
創(chuàng)建項(xiàng)目結(jié)構(gòu)
|-js |-dist //打包生成文件的目錄 |-src //源碼所在的目錄 |-module1.js |-module2.js |-module3.js |-app.js //應(yīng)用主源文件 |-index.html //瀏覽器上的頁面 |-package.json { "name": "browserify-test", "version": "1.0.0" }
下載browserify
全局: npm install browserify -g
局部: npm install browserify --save-dev
定義模塊代碼:index.html文件要運(yùn)行在瀏覽器上,需要借助browserify將app.js文件打包編譯,如果直接在index.html引入app.js就會報(bào)錯。
打包處理js:根目錄下運(yùn)行browserify js/src/app.js -o js/dist/bundle.js
頁面使用引入:
AMD : 瀏覽器端
CommonJS規(guī)范加載模塊是同步的,也就是說,只有加載完成,才能執(zhí)行后面的操作。
AMD規(guī)范則是非同步加載模塊,允許指定回調(diào)函數(shù),可以實(shí)現(xiàn)異步加載依賴模塊,并且會提前加載;
由于Node.js主要用于服務(wù)器編程,模塊文件一般都已經(jīng)存在于本地硬盤,所以加載起來比較快,不用考慮非同步加載的方式,所以CommonJS規(guī)范比較適用。
如果是瀏覽器環(huán)境,要從服務(wù)器端加載模塊,這時就必須采用非同步模式,因此瀏覽器端一般采用AMD規(guī)范。
語法定義暴露模塊: define([依賴模塊名], function(){return 模塊對象})
引入模塊: require(["模塊1", "模塊2", "模塊3"], function(m1, m2){//使用模塊對象})
define(function (require, exports, module) { var reqModule = require("./someModule"); requModule.test(); exports.asplode = function () { //someing } });AMD:異步模塊定義規(guī)范(預(yù)加載)
AMD規(guī)范:https://github.com/amdjs/amdj...
AMD是"Asynchronous Module Definition"的縮寫,意思就是"異步模塊定義"。
它采用異步方式加載模塊,模塊的加載不影響它后面語句的運(yùn)行。所有依賴這個模塊的語句,都定義在一個回調(diào)函數(shù)中,等到加載完成之后,這個回調(diào)函數(shù)才會運(yùn)行。
AMD也采用require()語句加載模塊,但是不同于CommonJS,它要求兩個參數(shù):
require([module], callback);
第一個參數(shù)[module],是一個數(shù)組,里面的成員就是要加載的模塊;
第二個參數(shù)callback,則是加載成功之后的回調(diào)函數(shù)。
目前,主要有兩個Javascript庫實(shí)現(xiàn)了AMD規(guī)范:RequireJS和curl.js。
RequireJS
優(yōu)點(diǎn)
實(shí)現(xiàn)js文件的異步加載,避免網(wǎng)頁失去響應(yīng);
管理模塊之間的依賴性,便于代碼的編寫和維護(hù)。
下載require.js, 并引入
官網(wǎng): https://requirejs.org/
中文:https://blog.csdn.net/sanxian...
github : https://github.com/requirejs/...
將require.js導(dǎo)入項(xiàng)目: js/libs/require.js
創(chuàng)建項(xiàng)目結(jié)構(gòu)
|-js |-libs |-require.js // 引入的require.js |-modules |-alerter.js |-dataService.js |-main.js |-index.html
定義require.js的模塊代碼
require.js加載的模塊,采用AMD規(guī)范。也就是說,模塊必須按照AMD的規(guī)定來寫。
具體來說,就是模塊必須采用特定的define()函數(shù)來定義;
如果一個模塊不依賴其他模塊,那么可以直接定義在define()函數(shù)之中。
define(["myLib"], function(myLib){ function foo(){ myLib.doSomething(); } // 暴露模塊 return {foo : foo}; }); //當(dāng)require()函數(shù)加載上面這個模塊的時候,就會先加載myLib.js文件。
- 如果這個模塊還依賴其他模塊,那么define()函數(shù)的第一個參數(shù),必須是一個數(shù)組,指明該模塊的依賴性; ``` // dataService.js define(function () { let msg = "this is dataService" function getMsg() { return msg.toUpperCase() } return {getMsg} }) // alerter.js define(["dataService", "jquery"], function (dataService, $) { let name = "Tom2" function showMsg() { $("body").css("background", "gray") alert(dataService.getMsg() + ", " + name) } return {showMsg} }) ```
應(yīng)用主(入口)js: main.js
使用require.config()方法,我們可以對模塊的加載行為進(jìn)行自定義。require.config()就寫在主模塊main.js的頭部,參數(shù)就是一個對象,這個對象的paths屬性指定各個模塊的加載路徑。
(function () { //配置 require.config({ //基本路徑 baseUrl: "js/", //模塊標(biāo)識名與模塊路徑映射 paths: { "alerter": "modules/alerter",//此處不能寫成alerter.js,會報(bào)錯 "dataService": "modules/dataService", } }) //引入使用模塊 require( ["alerter"], function(alerter) { alerter.showMsg() }) })()
頁面使用模塊:
require.config()接受一個配置對象,這個對象除了有前面說過的paths屬性之外,還有一個shim屬性,專門用來配置不兼容的模塊。
具體來說,每個模塊要定義:
1、exports值(輸出的變量名),表明這個模塊外部調(diào)用時的名稱;
2、deps數(shù)組,表明該模塊的依賴性。
支持的配置項(xiàng):
baseUrl :所有模塊的查找根路徑。
當(dāng)加載純.js文件(依賴字串以/開頭,或者以.js結(jié)尾,或者含有協(xié)議),不會使用baseUrl。
如未顯式設(shè)置baseUrl,則默認(rèn)值是加載require.js的HTML所處的位置。如果用了data-main屬性,則該路徑就變成baseUrl。
baseUrl可跟require.js頁面處于不同的域下,RequireJS腳本的加載是跨域的。唯一的限制是使用text! plugins加載文本內(nèi)容時,這些路徑應(yīng)跟頁面同域,至少在開發(fā)時應(yīng)這樣。優(yōu)化工具會將text! plugin資源內(nèi)聯(lián),因此在使用優(yōu)化工具之后你可以使用跨域引用text! plugin資源的那些資源。
paths:path映射那些不直接放置于baseUrl下的模塊名。
設(shè)置path時起始位置是相對于baseUrl的,除非該path設(shè)置以"/"開頭或含有URL協(xié)議(如http:)。
用于模塊名的path不應(yīng)含有.js后綴,因?yàn)橐粋€path有可能映射到一個目錄。路徑解析機(jī)制會自動在映射模塊名到path時添加上.js后綴。在文本模版之類的場景中使用require.toUrl()時它也會添加合適的后綴。
在瀏覽器中運(yùn)行時,可指定路徑的備選(fallbacks),以實(shí)現(xiàn)諸如首先指定了從CDN中加載,一旦CDN加載失敗則從本地位置中加載這類的機(jī)制;
shim: 為那些沒有使用define()來聲明依賴關(guān)系、設(shè)置模塊的"瀏覽器全局變量注入"型腳本做依賴和導(dǎo)出配置。
將jquery的庫文件導(dǎo)入到項(xiàng)目: js/libs/jquery-1.10.1.js
在main.js中配置jquery路徑
paths: { "jquery": "libs/jquery-1.10.1" }
在alerter.js中使用jquery
define(["dataService", "jquery"], function (dataService, $) { var name = "xfzhang" function showMsg() { $("body").css({background : "red"}) alert(name + " "+dataService.getMsg()) } return {showMsg} })
將angular.js導(dǎo)入項(xiàng)目:js/libs/angular.js
流行的函數(shù)庫(比如jQuery)符合AMD規(guī)范,更多的庫并不符合。這樣的模塊在用require()加載之前,要先用require.config()方法,定義它們的一些特征。
// main.js中配置 (function () { //配置 require.config({ //基本路徑 baseUrl: "js/", //模塊標(biāo)識名與模塊路徑映射 paths: { //第三方庫作為模塊 "jquery" : "./libs/jquery-1.10.1", "angular" : "./libs/angular", //自定義模塊 "alerter": "./modules/alerter", "dataService": "./modules/dataService" }, /* 配置不兼容AMD的模塊 exports : 指定與相對應(yīng)的模塊名對應(yīng)的模塊對象 */ shim: { "angular" : { exports : "angular" } } }) //引入使用模塊 require( ["alerter", "angular"], function(alerter, angular) { alerter.showMsg() console.log(angular); }) })()CMD : 瀏覽器端
CMD規(guī)范:https://github.com/seajs/seaj...
CMD規(guī)范專門用于瀏覽器端,模塊的加載是異步的,模塊使用時才會加載執(zhí)行。
CMD規(guī)范整合了CommonJS和AMD規(guī)范的特點(diǎn)。
在 Sea.js 中,所有 JavaScript 模塊都遵循 CMD模塊定義規(guī)范
基本語法
定義暴露模塊:
// 沒有依賴的模塊 define(function(require, module, exports){ let value = "xxx"; //通過require引入依賴模塊 //通過module.exports/exports來暴露模塊 exports.xxx = value module.exports = value }) // 有依賴的模塊 define(function(require, exports, module){ //引入依賴模塊(同步) var module2 = require("./module2") //引入依賴模塊(異步) require.async("./module3", function (m3) { ...... }) //暴露模塊 exports.xxx = value })
使用模塊seajs.use(["模塊1", "模塊2"])
sea.js簡單使用教程
下載sea.js, 并引入
官網(wǎng): http://seajs.org/
github : https://github.com/seajs/seajs
將sea.js導(dǎo)入項(xiàng)目: js/libs/sea.js
如何定義導(dǎo)出模塊 :
define() exports module.exports
如何依賴模塊:require()
如何使用模塊: seajs.use()
創(chuàng)建項(xiàng)目結(jié)構(gòu)
|-js |-libs |-sea.js |-modules |-module1.js |-module2.js |-module3.js |-module4.js |-main.js |-index.html
定義sea.js的模塊代碼
module1.js
define(function (require, exports, module) { //內(nèi)部變量數(shù)據(jù) var data = "this is module1" //內(nèi)部函數(shù) function show() { console.log("module1 show() " + data) } //向外暴露 exports.show = show })
module2.js
define(function (require, exports, module) { module.exports = { msg: "I Will Back" } })
module3.js
define(function (require, exports, module) { const API_KEY = "abc123" exports.API_KEY = API_KEY })
module4.js
define(function (require, exports, module) { //引入依賴模塊(同步) var module2 = require("./module2"); function show() { console.log("module4 show() " + module2.msg) } exports.show = show //引入依賴模塊(異步) require.async("./module3", function (m3) { console.log("異步引入依賴模塊3 " + m3.API_KEY) }) })
main.js : 主(入口)模塊
define(function (require) { var m1 = require("./module1") var m4 = require("./module4") m1.show() m4.show() })
index.html:
ES6模塊化
模塊化的規(guī)范:CommonJS和AMD兩種。前者用于服務(wù)器,后者用于瀏覽器。
而ES6 中提供了簡單的模塊系統(tǒng),完全可以取代現(xiàn)有的CommonJS和AMD規(guī)范,成為瀏覽器和服務(wù)器通用的模塊解決方案。
ES6 模塊的設(shè)計(jì)思想,是盡量的靜態(tài)化,使得編譯時就能確定模塊的依賴關(guān)系,以及輸入和輸出的變量。CommonJS 和 AMD 模塊,都只能在運(yùn)行時確定這些東西。
基本用法
es6 中新增了兩個命令 export 和 import ;
export 命令用于規(guī)定模塊的對外接口;
import 命令用于輸入其他模塊提供的功能。
一個模塊就是一個獨(dú)立的文件。該文件內(nèi)部的所有變量,外部無法獲取。
如果你希望外部能夠讀取模塊內(nèi)部的某個變量,就必須使用export關(guān)鍵字輸出該變量。
下面是一個JS文件,里面使用export命令輸出變量。
// math.js export const add = function (a, b) { return a + b } export const subtract = function (a, b) { return a - b }
使用export命令定義了模塊的對外接口以后,其他JS文件就可以通過import命令加載這個模塊(文件)。
// main.js import { add, subtract } from "./math.js" add(1, 2) substract(3, 2)
定義暴露模塊 : export
暴露一個對象:
默認(rèn)暴露,暴露任意數(shù)據(jù)類型,暴露什么數(shù)據(jù)類型,接收什么數(shù)據(jù)類型
export default 對象
暴露多個:
常規(guī)暴露,暴露的本質(zhì)是對象,接收的時候只能以對象的解構(gòu)賦值的方式來接收值
export var xxx = value1 export let yyy = value2 // 暴露一個對象 var xxx = value1 let yyy = value2 export {xxx, yyy}
引入使用模塊 : import
default模塊:
import xxx from "模塊路徑/模塊名"
其它模塊
import {xxx, yyy} from "模塊路徑/模塊名" import * as module1 from "模塊路徑/模塊名"export 詳細(xì)用法
export不止可以導(dǎo)出函數(shù),還可以導(dǎo)出,對象、類、字符串等等;
暴露多個:
分別暴露
export const obj = {test1: ""} export const test = "" export class Test { constuctor() { } } // 或者,直接在暴露的地方定義導(dǎo)出函數(shù)或者變量 export let foo = ()=>{console.log("fnFoo");return "foo"},bar="stringBar"
一起暴露,推薦使用這種寫法,這樣可以寫在腳本尾部,一眼就看清楚輸出了哪些變量。
let a=1 let b=2 let c=3 export { a,b,c }
還可以通過as改變輸出名稱
// test.js let a = 1 let b = 2 let c = 3 export { a as test, b, c }; import { test, b, c } from "./test.js" // 改變命名后只能寫 as 后的命名
通過通配符暴露其他引入的模塊
// test.js let a = 1 let b = 2 let c = 3 export { a as test, b, c }; // lib.js引入test.js的內(nèi)容 export * from "./test.js" // 引入 import {test,b,c} from "./lib.js"
暴露一個對象,默認(rèn)暴露
export default指定默認(rèn)輸出,import無需知道變量名就可以直接使用
// test.js export default function () { console.log("hello world") } //引入 import say from "./test.js" // 這里可以指定任意變量名 say() // hello world
常用的模塊
import $ from "jQuery" // 加載jQuery 庫 import _ from "lodash" // 加載 lodash import moment from "moment" // 加載 momentimport詳細(xì)用法
import 為加載模塊的命令,基礎(chǔ)使用方式和之前一樣
// main.js import { add, subtract } from "./test" // 對于export default 導(dǎo)出的 import say from "./test"
通過 as 命令修改導(dǎo)入的變量名
import {add as sum, subtract} from "./test" sum (1, 2)
加載模塊的全部,除了指定輸出變量名或者 export.default 定義的導(dǎo)入, 還可以通過 * 號加載模塊的全部。
// math.js export const add = function (a, b) { return a + b } export const subtract = function (a, b) { return a - b } //引入 import * as math from "./test.js" math.add(1, 2) math.subtract(1, 2)ES6-Babel-Browserify使用教程
問題: 所有瀏覽器還不能直接識別ES6模塊化的語法
解決:
使用Babel將ES6--->ES5(使用了CommonJS) ----瀏覽器還不能直接執(zhí)行;
使用Browserify--->打包處理js----瀏覽器可以運(yùn)行
定義package.json文件
{ "name" : "es6-babel-browserify", "version" : "1.0.0" }
安裝babel-cli, babel-preset-es2015和browserify
npm install babel-cli browserify -g npm install babel-preset-es2015 --save-dev
定義.babelrc文件,這是一個babel的設(shè)置文件
{ "presets": ["es2015"] }
編碼
// js/src/module1.js export function foo() { console.log("module1 foo()"); }; export let bar = function () { console.log("module1 bar()"); }; export const DATA_ARR = [1, 3, 5, 1]; // js/src/module2.js let data = "module2 data"; function fun1() { console.log("module2 fun1() " + data); }; function fun2() { console.log("module2 fun2() " + data); }; export {fun1, fun2}; // js/src/module3.js export default { name: "Tom", setName: function (name) { this.name = name } } // js/src/app.js import {foo, bar} from "./module1" import {DATA_ARR} from "./module1" import {fun1, fun2} from "./module2" import person from "./module3" import $ from "jquery" //引入完畢 $("body").css("background", "red") foo() bar() console.log(DATA_ARR); fun1() fun2() person.setName("JACK") console.log(person.name);
編譯
使用Babel將ES6編譯為ES5代碼(但包含CommonJS語法) : babel js/src -d js/lib
使用Browserify編譯js : browserify js/lib/app.js -o js/lib/bundle.js
頁面中引入測試
引入第三方模塊(jQuery)
1). 下載jQuery模塊:
npm install jquery@1 --save
- 2). 在app.js中引入并使用 ``` import $ from "jquery" $("body").css("background", "red") ```總結(jié)
模塊化方案 | 優(yōu)點(diǎn) | 缺點(diǎn) |
---|---|---|
commonJS | 復(fù)用性強(qiáng); 使用簡單; 實(shí)現(xiàn)簡單; |
有不少可以拿來即用的模塊,生態(tài)不錯; 同步加載不適合瀏覽器,瀏覽器的請求都是異步加載; 不能并行加載多個模塊。 |
AMD | 異步加載適合瀏覽器 | 可并行加載多個模塊; 模塊定義方式不優(yōu)雅,不符合標(biāo)準(zhǔn)模塊化 |
ES6 | 可靜態(tài)分析,提前編譯 | 面向未來的標(biāo)準(zhǔn); 瀏覽器原生兼容性差,所以一般都編譯成ES5; 目前可以拿來即用的模塊少,生態(tài)差 |
權(quán)威參考:https://github.com/seajs/seaj...
對于依賴的模塊,AMD 是提前執(zhí)行,CMD 是延遲執(zhí)行。
不過 RequireJS 從 2.0 開始,也改成可以延遲執(zhí)行(根據(jù)寫法不同,處理方式不同)。CMD 推崇 as lazy as possible.
CMD 推崇依賴就近,AMD 推崇依賴前置。
// CMD define(function(require, exports, module) { var a = require("./a"); a.doSomething() // 此處略去 100 行 var b = require("./b") // 依賴可以就近書寫 b.doSomething() // ... }) // AMD 默認(rèn)推薦的是 define(["./a", "./b"], function(a, b) { // 依賴必須一開始就寫好 a.doSomething() // 此處略去 100 行 b.doSomething() ...})
雖然 AMD 也支持 CMD 的寫法,同時還支持將 require 作為依賴項(xiàng)傳遞,但 RequireJS 的作者默認(rèn)是最喜歡上面的寫法,也是官方文檔里默認(rèn)的模塊定義寫法。
AMD 的 API 默認(rèn)是一個當(dāng)多個用,CMD 的 API 嚴(yán)格區(qū)分,推崇職責(zé)單一。比如 AMD 里,require 分全局 require 和局部 require,都叫 require。CMD 里,沒有全局 require,而是根據(jù)模塊系統(tǒng)的完備性,提供 seajs.use 來實(shí)現(xiàn)模塊系統(tǒng)的加載啟動。CMD 里,每個 API 都簡單純粹。
還有一些細(xì)節(jié)差異,具體看這個規(guī)范的定義就好,就不多說了。
參考:使用 AMD、CommonJS 及 ES Harmony 編寫模塊化的 JavaScript
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/103478.html
摘要:收藏優(yōu)秀組件庫合集前端掘金開源的優(yōu)秀組件庫合集教你如何在應(yīng)用程序中使用本地文件上傳圖片前端掘金使用在中添加到的,現(xiàn)在可以讓內(nèi)容要求用戶選擇本地文件,然后讀取這些文件的內(nèi)容。 『收藏』VUE 優(yōu)秀 UI 組件庫合集 - 前端 - 掘金github 開源的 Vue 優(yōu)秀 UI 組件庫合集?... 教你如何在 web 應(yīng)用程序中使用本地文件?上傳圖片file? - 前端 - 掘金使用在HTM...
摘要:就鹿晗宣布戀情導(dǎo)致微博宕機(jī)事件淺談大型網(wǎng)站高可用性架構(gòu)中午吃飯刷著刷著微博發(fā)現(xiàn)微博突然掛了。用戶在使用瀏覽器訪問一個網(wǎng)站時需要先通過協(xié)議向服務(wù)器發(fā)送請求,之后服務(wù)器返回文件與響應(yīng)信息。 webpack:從入門到真實(shí)項(xiàng)目配置 自從出現(xiàn)模塊化以后,大家可以將原本一坨代碼分離到個個模塊中,但是由此引發(fā)了一個問題。每個 JS 文件都需要從服務(wù)器去拿,由此會導(dǎo)致加載速度變慢。Webpack 最主...
閱讀 1113·2021-11-23 09:51
閱讀 1080·2021-10-18 13:31
閱讀 2979·2021-09-22 16:06
閱讀 4273·2021-09-10 11:19
閱讀 2204·2019-08-29 17:04
閱讀 432·2019-08-29 10:55
閱讀 2482·2019-08-26 16:37
閱讀 3379·2019-08-26 13:29