跳转到主要内容

主页内容

JavaScript模块化详解(二) ES6模块化规范

由 webadmin 发布于 阅读 46 次

ES6模块化规范

ES6 模块化规范是一个官方标准的规范,它是在语言标准的层面上实现了模块化功能,是目前最流行的模块化规范,且浏览器与服务端均支持该规范。

1、初体验

新建:school.js

export const name = "清华大学";
export const slogan = "是中国最难考的大学吗?";
export function getTel(){
    return "010-89898989";
}

function getCities(){
    return ["北京","上海","天津"];
}

新建:student.js

export const name = "张三";
export const motto = "明天会更好";
export function getTel(){
    return "13201567876";
}

export function getHobby(){
    return ["打篮球","踢足球","上网"];
}

在以上两个js文件中,都使用了export来暴露数据。

新建:main.js

import * as school from "./school.js";
console.log(school);
console.log(school.name);

main.js中通过import关键字导入暴露的数据。*代表导入模块下所有的暴露数据。

新建:index.html,并引入main.js文件。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="main.js" type="module"></script>
</head>
<body>   
</body>
</html>

因为main.js是一个模块化的js,所以引入的时候必须用type="module"否则将不能识别模块化。

运行index.html结果如下:

2、Node中运行ES6模块的两种方式
2.1、通过修改js文件扩展名的方式让模块化的js能在Node下运行。

.js的扩展名改成.mjs。然后直接运行。

2.2、通过增加package.json配置文件的方式使模块化的js能在Node下运行。

在项目目录下新增package.json文件:

{
    "type": "module"
}
3、导出数据

ES6 模块化提供3种导出方式:分别导出、统一导出、默认导出。

3.1、分别导出
export const name = "清华大学";
export const slogan = "是中国最难考的大学吗?";
export function getTel(){
    return "010-89898989";
}

function getCities(){
    return ["北京","上海","天津"];
}

像上面这种,给每一个需要导出的数据前面加export关键字的导出形式就是分别导出。

3.2、统一导出
const name = "清华大学";
const slogan = "是中国最难考的大学吗?";
function getTel(){
    return "010-89898989";
}

function getCities(){
    return ["北京","上海","天津"];
}

//使用统一导出的方式暴露数据
export { name, slogan, getTel };

在以上的代码中,export { name, slogan, getTel };这句代码就是统一导出的方式暴露数据。相较于分别导出的方式来说,统一导出的方式不用给每个需要导出的数据前面加export关键字,而在代码最后通过一行简单的代码就实现了数据的导出。

3.3、默认导出
const name = "清华大学";
const slogan = "是中国最难考的大学吗?";
function getTel(){
    return "010-89898989";
}

function getCities(){
    return ["北京","上海","天津"];
}
//默认导出
export default {name, slogan, getTel};

以上代码中export default {name, slogan, getTel};是使用默认导出的方法暴露数据。这种数据被绑定在一个default属性上。在调用的时候区别于其他的方式,需要在default属性上来获取暴露的数据:

import * as school from "./school.js";
console.log(school);
//要使用:school.default.name来获取暴露的数据,而不是school.name
console.log(school.default.name);
3.4、以上三种方式可以混合使用
export const name = "清华大学";//使用了分别导出
const slogan = "是中国最难考的大学吗?";
function getTel(){
    return "010-89898989";
}

function getCities(){
    return ["北京","上海","天津"];
}

//使用了统一导出
export { slogan };

//使用了默认导出
export default {getTel};

以上代码中使用了分别导出、统一导出和默认导出三种方式。

4、导入数据

对于 ES6模块化来说,使用何种导入方式,要根据导出方式决定。

4.1、导入全部(通用)
import * as school from "./school.js";

获取导入数据的方式:

school.xxxschool.default.xxx(默认暴露的情况下)

4.2、命名导入(对应导出方式:分别导出、统一导出)

school.js代码:

const name = "清华大学";
const slogan = "是中国最难考的大学吗?";
function getTel(){
    return "010-89898989";
}

function getCities(){
    return ["北京","上海","天津"];
}
export {name, slogan};//使用了统一导出的方式

命名导入:

import {name, slogan} from "./school.js";
console.log(name);
console.log(slogan);

命名导入可以使用as关键字来重命名:

import {name as schoolName, slogan as schoolSlogan} from "./school.js";
console.log(schoolName);
console.log(schoolSlogan);

运行结果:

4.3、默认导入(对应导出方式:默认导出)

schoo.js代码:

const name = "清华大学";
const slogan = "是中国最难考的大学吗?";
function getTel(){
    return "010-89898989";
}

function getCities(){
    return ["北京","上海","天津"];
}
//使用默认导出
export default{name, slogan, getTel};

默认引入:

import school from "./school.js";
console.log(school);

运行结果:

4.4、不同导入方式可以混用

school.js代码:

export const name = "清华大学";//使用分别导出
const slogan = "是中国最难考的大学吗?";
function getTel(){
    return "010-89898989";
}
function getCities(){
    return ["北京","上海","天津"];
}
export {slogan};//使用统一导出

export default{getTel};//使用默认导出
//默认导出的时候如果只有一个数据可以省略花括号:export default getTel;

混合导入:

import school,{name, slogan} from "./school.js";
console.log(school);
console.log(name);
console.log(slogan);

运行结果:

4.5、动态导入(通用)

在特定时间点或特定操作下导入模块。

例如:页面上有一个按钮,用户点击后导入模块。

在页面中添加一个按钮:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="main.js" type="module"></script>
</head>
<body>
    <p>点击按钮导入模块</p>
    <button id="btn">导入模块</button>
</body>
</html>

main.js中点击按钮导入模块:

//使用动态导入
let btn = document.getElementById("btn");
btn.onclick = async()=>{
    const student = await import("./student.js");
    console.log(student);
}

运行结果:

4.6、import可以不接收任何数据

例如:有一个文件中的一些代码希望在每次项目启动的时候自动执行。

新建log.js

console.log(Math.random());

这个文件的作用是每次都输出一个随机数。没有任何暴露数据。

main.js中使用import导入:

import './log.js';

运行结果:

5、ES6的数据引用问题

data.js

let sum = 1;
function increment(){
    sum += 1;
    console.log('data',sum);
}
export {sum, increment};

main.js中导入并使用:

import {sum, increment} from './data.js';
console.log(sum);
increment();
increment();
console.log(sum);

运行结果:

在模块中定义需要导出的数据的时候,需要使用常量,避免在使用过程中值被改变。