# 07 TypeScript中的模块化

# 模块化概念

在JS的项目中,随着工程的不断增大,为了便于管理和模块复用,产生了很多模块化解决方案,如CommonJS,AMD,CMD及ES模块,目前最常用的是ES6的模块和CommonJS模块

TS对这两种模块系统都有比较好的支持。

TypeScript 1.5中术语名发生变化,“内部模块”现称作“命名空间”(见[08-namespace.md]),“外部模块”现简称为“模块”,模块在自身的作用域里执行,而不是全局作用。这就意味着定义在模块内部的变量、函数、类等等在模块外是不可见的,除非你明确的使用export形式之一导出它,否则,这些模块内的变量、函数、接口等都是私有的,外部不可调用。相应的,如果想使用其他模块到处的变量、函数、类和接口等,你必须要是用import形式之一导入它。

# 模块的导出、导入方式

新建一个lib.ts文件,并导出相关函数:

export function printString(str: string): void {
    console.log(`打印输出 ${str}`);
}

在另一个文件中07-modules.ts中导入lib,并指定要导入的函数名:

import {printString} from './lib'

printString("武汉加油,战疫必胜。");

然而,页面直接引入编译后生成的07-modules.js会报错:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });//Uncaught ReferenceError: exports is not defined
var lib_1 = require("./lib");
lib_1.printString("武汉加油,战疫必胜。");

这是因为浏览器并不能识别这样的模块化管理,这就需要借助到node.jswebpack这些打包工具,将源码打包成浏览器可识别的ES5语法。

我们可以使用node.js测试一下刚才的代码,cd到编译生成js的目录:

> cd 07-modules

执行:

> node 07-modules.js
打印输出 武汉加油,战疫必胜。

如期输出了我们预期的结果。


上面的例子中,我们使用export关键字导出模块内的方法,其实也可以这样导出变量,如:

export var config = {
    //...
};

但实际中,我们用的模块内方法变量以及接口众多,每个都在前面加export就有些不方便了。其实还有一种导出方法,在文档末尾加上:

export {
    variable,
    function1,
    function2
}

引入时:

import {variable,function1,function2} from './lib'

function1();
function2(variable);

有时,方法名、变量名太长太复杂也可以使用as关键字设置别名简化使用:

import {variable,function1 as fun1,function2 as fun2} from './lib'

fun1();
fun2(variable);

# export default 默认导出

每个模块都可以有一个default导出。默认导出使用default关键字标记,并且一个模块只能够有一个default导出。

export default function1;

default导出的需要使用一种特殊导入形式

import function1 from './lib'

function1();