模塊化
把復(fù)雜的問(wèn)題分解成相對(duì)獨(dú)立的模塊,降低程序復(fù)雜性埋虹,提高代碼的重用堪遂。
- commonJS
- AMD
- CMD
- UMD
- ESM
模塊化的核心
- 獨(dú)立的作用域(一個(gè)文件就是模塊秩冈,擁有獨(dú)立的作用域,且導(dǎo)出的模塊都自動(dòng)處于
嚴(yán)格模式
下沃测,即'use strict'
) - 如何導(dǎo)出模塊內(nèi)部數(shù)據(jù)
- 如何導(dǎo)入外部模塊數(shù)據(jù)
導(dǎo)出模塊
// 導(dǎo)出單個(gè)
export let name1,name2, ..., nameN;
export let name1 = ...,name2 = ..., nameN;
export function funName() { ... }
export class className { ... }
// 導(dǎo)出列表
export { name1, name2, ..., nameN };
// 重命令導(dǎo)出
export { variable1 as name1, variable2 as name2, ..., nameN };
// 默認(rèn)導(dǎo)出
export default function(...) {...}
export default expression;
export default function name(...) { ... }
export { name1 as default, ... }
// 模塊重定向?qū)С?export * from ...;
export { name1,name2 } from ...;
export { import1 as name1, import2 as name2 } from ...;
export { default } from ...;
導(dǎo)入模塊
靜態(tài)導(dǎo)入
在瀏覽器缭黔,import
語(yǔ)句只能在聲明了type="module"
的 script 的標(biāo)簽中使用
import defaultExport from "module-name";
import * as name from "module-name";
import { export } from "module-name";
import { export as alias } from "module-name";
import { export1 , export2 } from "module-name";
import { foo , bar } from "module-name/path/to/specific/un-exported/file";
import { export1 , export2 as alias2 , [...] } from "module-name";
import defaultExport, { export [ , [...] ] } from "module-name";
import defaultExport, * as name from "module-name";
import "module-name";
靜態(tài)導(dǎo)入方式不支持延遲加載,
import
必須這模塊的最開(kāi)始
document.onclick = function () {
// import 必須放置在當(dāng)前模塊最開(kāi)始加載
import m1 from './m1.js'
console.log(m1);
}
動(dòng)態(tài)導(dǎo)入
此外蒂破,還有一個(gè)類似函數(shù)的動(dòng)態(tài) import()
馏谨,它不需要依賴 type="module"
的 script 標(biāo)簽。
關(guān)鍵字 import
可以像調(diào)用函數(shù)一樣來(lái)動(dòng)態(tài)的導(dǎo)入模塊。以這種方式調(diào)用,將返回一個(gè) promise
鱼的。
import('./m.js')
.then(m => {
//...
});
// 也支持 await
let m = await import('./m.js');
通過(guò)
import()
方法導(dǎo)入返回的數(shù)據(jù)會(huì)被包裝在一個(gè)對(duì)象中,即使是default
也是如此
CommonJS
在早起前端對(duì)于模塊化并沒(méi)有什么規(guī)范喊儡,反而是偏向服務(wù)端的應(yīng)用有更強(qiáng)烈的需求,CommonJS 規(guī)范就是一套偏向服務(wù)端的模塊化規(guī)范稻据,NodeJS 就采用了這個(gè)規(guī)范管宵。
獨(dú)立模塊作用域
一個(gè)文件就是模塊,擁有獨(dú)立的作用域
導(dǎo)出模塊內(nèi)部數(shù)據(jù)
通過(guò) module.exports
或 exports
對(duì)象導(dǎo)出模塊內(nèi)部數(shù)據(jù)
// a.js
let a = 1;
let b = 2;
module.exports = {
x: a,
y: b
}
// or
exports.x = a;
exports.y = b;
導(dǎo)入外部模塊數(shù)據(jù)
通過(guò) require
函數(shù)導(dǎo)入外部模塊數(shù)據(jù)
// b.js
let a = require('./a');
a.x;
a.y;
AMD
因?yàn)?CommonJS 規(guī)范一些特性(基于文件系統(tǒng),同步加載)箩朴,它并不適用于瀏覽器端岗喉,所以另外定義了適用于瀏覽器端的規(guī)范
AMD(Asynchronous Module Definition)
https://github.com/amdjs/amdjs-api/wiki/AMD
瀏覽器并沒(méi)有具體實(shí)現(xiàn)該規(guī)范的代碼,我們可以通過(guò)一些第三方庫(kù)來(lái)解決
requireJS
// 1.html
<script data-main="scripts/main" src="https://cdn.bootcss.com/require.js/2.3.6/require.min.js"></script>
獨(dú)立模塊作用域
通過(guò)一個(gè) define
方法來(lái)定義一個(gè)模塊炸庞,并通過(guò)該方法的第二個(gè)回調(diào)函數(shù)參數(shù)來(lái)產(chǎn)生獨(dú)立作用域
// scripts/Cart.js
define(function() {
// 模塊內(nèi)部代碼
})
導(dǎo)出模塊內(nèi)部數(shù)據(jù)
通過(guò) return
導(dǎo)出模塊內(nèi)部數(shù)據(jù)
// scripts/Cart.js
define(function() {
return class Cart {
add(item) {
console.log(`添加商品:${item}`)
}
}
})
導(dǎo)入外部模塊數(shù)據(jù)
通過(guò)前置依賴列表導(dǎo)入外部模塊數(shù)據(jù)
// scripts/main.js
// 定義一個(gè)模塊钱床,并導(dǎo)入 ./Cart 模塊
define(['./Cart'], function(Cart) {
let cart = new Cart()
cart.add({name: 'iphoneXX', price: 1000000})
})
requireJS 的 CommonJS 風(fēng)格
require.js
也支持 CommonJS
風(fēng)格的語(yǔ)法
導(dǎo)出模塊內(nèi)部數(shù)據(jù)
// scripts/Cart.js
define(['require', 'exports', 'module'], function(require, exports, module) {
class Cart {
add(item) {
console.log(`添加商品:${item}`)
}
}
exports.Cart = Cart;
})
// 忽略不需要的依賴導(dǎo)入
define(['exports'], function(exports) {
class Cart {
add(item) {
console.log(`添加商品:${item}`)
}
}
exports.Cart = Cart;
})
// 如果是依賴的導(dǎo)入為:require, exports, module,也可以省略依賴導(dǎo)入聲明
define(function(require, exports, module) {
class Cart {
add(item) {
console.log(`添加商品:${item}`)
}
}
exports.Cart = Cart;
})
導(dǎo)入外部模塊數(shù)據(jù)
// scripts/main.js
define(['./Cart'], function(Cart) {
let cart = new Cart()
cart.add({name: 'iphoneXX', price: 1000000})
})
UMD
嚴(yán)格來(lái)說(shuō)埠居,UMD
并不屬于一套模塊規(guī)范查牌,它主要用來(lái)處理 CommonJS
、AMD
滥壕、CMD
的差異兼容纸颜,是模塊代碼能在前面不同的模塊環(huán)境下都能正常運(yùn)行
(function (root, factory) {
if (typeof module === "object" && typeof module.exports === "object") {
// Node, CommonJS-like
module.exports = factory(require('jquery'));
}
else if (typeof define === "function" && define.amd) {
// AMD 模塊環(huán)境下
define(['jquery'], factory);
}
}(this, function ($) { // $ 要導(dǎo)入的外部依賴模塊
$('div')
// ...
function b(){}
function c(){}
// 模塊導(dǎo)出數(shù)據(jù)
return {
b: b,
c: c
}
}));