ES6 模块你必须知道的

最近,我在学习 Vue 3,一直以来想学习的,不过都没什么动力去学习。这次正好有个小项目,我可以借机学习一下。我这才发现,真是举步维艰,我对前端开发的知识,停留在 jQuery + Bootstrap 时代,这么多年就没有进步过。现在一上手,才深刻体会到自己的落伍。

我要想成功把项目给开发出来,必须从最基础的知识开始补课,才能完成目标。模块,就是我第一个要学会的知识。

模块

熟悉后端开发,模块就是一个常见的组织代码进行复用的抽象概念。在后端开发领域,模块,类库等等都是联系在一起的概念。比如,在 PHP 里,就是用 require 语句来引入一个模块,模块可以是一段代码,也可以是一个类等等。在 Yii 框架里,有关于 Module 的抽象,可以用 DI 或者 Service Locator 等方式来引入到项目里。

随着 Javascript 脚本规模变得越来越庞大,出于对管理复杂度的需求,以及代码复用的需求,模块也成为 Javascript 比较重要的特性。尤其是 Node.js 很早就开始提供这个特性了。还有很多的类库和框架也各自提供了模块的抽象概念,所以渐渐语言层面也开始原生支持模块这个特性了。

export 语句

为了获得模块的功能,第一步是使用 export 语句将其导出。

导出的两种方式

导出有两种,命名导出和默认导出。一个模块,可以导出任意多个命名导出。但是只能有一个默认导出。

使用 let,var,const 声明的变量,function 和 class 都可以作为命名导出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 导出单个特性
export let name1, name2, …, nameN; // also var, const
export let name1 = …, name2 = …, …, nameN; // also var, const
export function FunctionName(){...}
export class ClassName {...}

// 导出列表
export { name1, name2, …, nameN };

// 重命名导出
export { variable1 as name1, variable2 as name2, …, nameN };

// 解构导出并重命名
export const { name1, name2: bar } = o;

// 默认导出
export default expression;
export default function () { … } // also class, function*
export default function name1() { … } // also class, function*
export { name1 as default, … };

// 导出模块合集
export * from …; // does not set the default export
export * as name1 from …; // Draft ECMAScript® 2O21
export { name1, name2, …, nameN } from …;
export { import1 as name1, import2 as name2, …, nameN } from …;
export { default } from …;

关于导出语句的语法形式。

命名导出,在导入的时候,必须使用相应对象的相同名称。但是,可以使用任意名称来导入默认导出。

重导出/聚合

可以在一个文件中,将多个模块导出,这样就可以在另一个文件中,只导入一个文件,就可以使用多个模块了。

import 语句

导入分为静态导入和动态导入,动态导入是一个方法的调用 import(),而静态导出是一个 js 语句。静态导入是初始化加载依赖项的最优选择,使用静态 import 更容易从代码静态分析工具和 tree shaking 中受益。

1
2
3
4
5
6
7
8
9
10
11
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";
var promise = import("module-name");//这是一个处于第三阶段的提案。

以上是 import 语句的各种语法形式。

如果不用大括号,就是导入默认导出的符号。使用大括号,就是导入命名导出的符号。

导入整个模块的内容

使用 * 可以导入整个模块的内容,使用 as 可以将模块的内容都置于一个作用域内,避免名字的冲突。

作为副作用导入一个模块

1
import '/modules/my-module.js';

这种不使用 from 语句的导入,导入了一个模块的所有副作用,其中的一些代码会执行,但是,本质上没有导入任何符号。

总结

以上是我对模块相关功能的一些笔记,如果不了解这些知识,是很难看懂 Vue 3 的项目代码的,因为应用一般是用模块进行组织的,会大量出现 import export 语句,知道这些基本用法是非常有必要的。