前端模塊化之ES Module


一、概述

之前提到的幾種模塊化規范:CommonJS、AMD、CMD都是社區提出的。ES 2015在語言層面上實現了模塊功能,且實現簡單,可以替代CommonJS和AMD規范,成為在服務器和瀏覽器通用的解決方案

二、特性

1、ES Module自動啟用嚴格模式

 <script type="module">
        console.log(this); //undefined
  </script>

2、ES Module運行在單獨的作用域中,與外界互不干擾

    <script type="module">
        var foo = 100;
        console.log(foo);//100
    </script>
    <script type="module">
        console.log(foo);//Uncaught ReferenceError: foo is not defined
    </script>

3、ES Module是通過CORS方式請求外部文件,需外部文件支持CORS請求

 //該文件支持CORS請求,則可以請求成功
<script type="module" src="http://code.jquery.com/jquery-migrate-1.2.1.min.js"></script>

//該文件不支持CORS請求,報跨域錯誤
<script type="module" src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script> 

4、ES Module引用的文件會延遲執行

//index.js
alert('hello');
//index.html
<body>
	<script type="module" src="./index.js"></script> 等價於   <script defer src="./index.js"></script>
	<p>
             文本內容
        </p>
</body>

執行結果【js的加載並未影響到DOM的加載】

三、export命令

由於在ES Module中,每個模塊都是一個單獨的作用域,如果想使模塊內的變量暴露出去,使用export關鍵字,導入其他模塊的關鍵字使用import

1、挨個導出變量

//module.js
export var name = "張三";

export function add(a, b) {
    return a + b;
}

export var obj = {
    name: 'jack'
};

2、批量導出變量

//module.js
var name = "張三";

function add(a, b) {
    return a + b;
}

var obj = {
    name: 'jack'
};

export { name, add, obj }

優點:在腳本尾部,使用一個export統一導出,清晰簡潔

3、導出默認數據

//module.js
export default 'es module'
或者
export default function(a,b){
	return a+b;
}

注意:說完import后再說注意事項

4、導出時起別名,使用as關鍵字

//module.js
var name = "張三";

function add(a, b) {
    return a + b;
}

var obj = {
    name: 'jack'
};

export { name as v1, add as v2, obj as v3}

四、import命令

要想接受其他模塊通過export導出的成員時,使用import關鍵字

1、import導入其他模塊中的變量

//module.js
var name = "張三";

function add(a, b) {
    return a + b;
} 

export { name ,add }
//app.js
import { name, add as MathAdd} from "./module.js"
console.log(name);//張三
console.log(MathAdd(1, 1)) //2

注意:

1.1使用相對路徑 后綴名和./不能省略

​ import {name} from "./module.js"

1.2使用絕對路徑

​ import {name} from "/demo/module.js"

1.3使用全路徑

​ import {name} from "http://localhost:8080/demo/module.js"

1.4可以在導入模塊時使用as 起別名

​ 起別名后,as前的變量不可使用了

2、使用import只執行引入文件,不提取引入文件中的成員時

  1. import {} from "./module.js";
  2. import './module.js'【常用】
//module.js
console.log('module.js中執行')

var name = "張三";

function add(a, b) {
    return a + b;
}

var obj = {
    name: 'jack'
};

export { name, add, obj }
//app.js
import {} from "./module.js";
或者寫成
import './module.js'
//index.html
<body>
    <script type="module" src="./app.js"></script>
    //執行結果
    //module.js中執行
</body>

當多次執行同一個import語句時,只會執行一次

3、模塊的整體加載

使用import除了可以加載單個值,也可以一次性加載模塊導出的所有值

//module.js

var name = "張三";

function add(a, b) {
    return a + b;
}

var obj = {
    name: 'jack'
};

export { name, add, obj }
//app.js
import * as all './module.js'
console.log('name:',all.name);
console.log('obj',all.obj);
console.log(add(1,1))

五、export default

前面使用export導出模塊內的成員時,需要指定具體的成員名稱,同樣加載時需要根據導出的具體名稱進行加載。還有一種快捷的導出方式,使用export default 為模塊指定默認導出,每個模塊只能使用一次export default

1、導出匿名成員時,使用任意變量接受成員

//module.js
export default function(a, b) {
    return a + b;
}
 //app.js
 import add from "./module.js"; 
 console.log(add(1,2));

因為使用export導出成員時是匿名的,所以在導入時並不知道這個成員的名字是什么,這時候就可以隨意寫變量去接受這個匿名成員,案例中使用add接受的匿名函數,也可以使用其他名稱接收。

注意:export default也可以導出具名成員,但效果和導出匿名成員是一樣的

//module.js
export default function add(a, b) {
    return a + b;
}
//或者
function add(a,b){
    return a + b;
}
export default add
 //app.js
 import temp from "./module.js"; 
 console.log(temp(1,2));

總結:使用export default導出成員,在外部加載時都視為匿名成員加載,可以隨意起變量名接受

2、同時導入其他模塊的默認成員和具名成員時

//module.js
var name = 'jack';
var age = 19;
export { name, age } 

//導出默認成員
export default 'default export'
//app.js
import str,{name,age} from "./module.js";
或者
import {name,age,default as str} from "./module.js"
console.log(str);//default export
console.log(name);//jack
console.log(age);//19

3、另類的默認導出

//module.js
var number = 1;
export { number as default }
等同於
export default number;
//app.js
import { default as number} from "./module.js"
console.log(number); //1

總結:可見export default的本質就是導出一個名字叫default的成員,當導出的成員叫default時,接受這個成員可以隨意命名

4、使用export default來導出類

//Person.js
export default class Person(){
    ....
}


//main.js
import Person from "./Person.js";
const person = new Person();

5、比較一下默認輸出和正常輸出

//1.默認輸出
export default function add(a,b){
    return a + b;
}
//接受默認輸出
import temp from './module.js'

//2.具名輸出
function add (a,b){
    return a + b;
}
export {add}
//接受具名輸出
import {add} from './module.js'

總結:使用默認導出時,在外部接受成員,不需要使用大括號;使用具名輸出時,在外部接受成員時,import后需要使用大括號

六、迷惑性的點

1、export批量導出變量時,導出的並不是對象字面量

//module.js
var name = 'jack';
var age = 19;
export { name, age } 
//export {name,age} 並不是導出的一個對象,而是export批量導出的語法

2、import加載多個變量時,並不是ES6的解構用法

import {name,age} from "./module.js"
//impot后面的大括號並不是解構作用

3、import導入的變量都是常量,不可修改,與CommonJS不同

七、export和import的復合用法

當我們在文件內import一個成員后,同時把它導出時

//index.js
import {Button} from './button.js'
export { Button }

可以寫成

export {Button} from "./button.js"

八、import()函數

import關鍵字導入其他模塊成員時,必須寫在最頂層作用域,不可嵌套在其他邏輯處理中。如果說我們想在某段邏輯執行完成后去動態加載某些成員,這時候可以使用import()函數加載

//module.js
var name = "張三";

function add(a, b) {
    return a + b;
}

var obj = {
    name: 'jack'
};

export { name, add, obj }
export default function() {
    return '匿名成員'
}
//app.js
//使用setTimeout來模擬一個異步加載的過程
setTimeout(() => {
    //import返回的是個promise,返回的模塊內容都在回調函數的參數中(moduleResult)
    import ("./module.js").then(moduleResult => {
        console.log(moduleResult)
        console.log(moduleResult.add)
        console.log(moduleResult.name)
        console.log(moduleResult.default)
        console.log(moduleResult.obj)
    })
    
    //也可以直接把成員結構出來
       import ("./module.js").then(({add,name,obj,default:defaultData}}) => {
        console.log(moduleResult.add)
        console.log(moduleResult.name)
        console.log(moduleResult.defaultData)
        console.log(moduleResult.obj)
    })
}, 2000);


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM