TS模块化规范与命名空间

模块化规范:

AMD、CMD、CommonJS、ES Module

在这里插入图片描述

CommonJS规范主要是为了弥补JavaScript没有标准的缺陷,已达到像Python、Ruby和Java那样具备开发大型应用的基础能力,而不是停留在开发浏览器端小脚本程序的阶段。使用CommonJS规范进行开发,需要依赖Node.js环境。(例如浏览器不兼容CommonJS的根本原因,在于缺少四个Node.js环境的变量:module、exports、require、global)

AMD规范(异步模块定义)是 RequireJS 在推广过程中对模块定义的规范化产出,不是JavaScript原生支持。使用AMD规范进行开发时,需要引入RequireJS这个第三方函数库,通过define()来定义模块,采用require()语句来加载模块。

CMD(通用模块定义)是 SeaJS 在推广过程中对模块定义的规范化产出。使用CMD规范进行开发时,需要引入SeaJS这个第三方函数库。在CMD规范中,一个模块就是一个文件,使用define()语句定义模块,使用seajs.use()加载模块。

注:
UMD 叫做通用模块定义规范,也是前端模块化演变出的一种模块化定义,是模块定义的跨平台解决方案。它支持运行时让同一个代码的模块,在使用 Commonjs、AMD等其他模块化规范项目中运行,换句话说,UMD可以让你的代码兼容基于其他多种模块化规范写的模块,统一浏览器端以及非浏览器端的模块化方案的规范,通用性很强,但本质上他没有自己的“规范”,他其实就是个集合,将Commonds、AMD等规范汇聚于-体,就可以同时支持import、require 和script直接引用。
使用场景:
假设你现在有一个场景:你需要开发一个工具库,一个util的方法,与此同时你想让这个代码(开发的类库)既能在nodejs环境直接使用,又能在浏览器中使用,那么我们就使用umd的输出模式,只需在webpack 的 output 中添加 libraryTarget:UMD,即可,就可以更好地解决跨平台、跨环境等问题。

三者的区别:

CommonJS规范加载模块是同步的,也就是说,只有加载完成,才能执行后面的操作。

AMD是异步加载模块,核心是预加载,先对依赖的全部文件进行加载,加载完了再进行处理。

CMD也是异步加载模块,是按需加载。AMD和CMD最大的区别是对依赖模块的执行时机不同,而不是加载时机不同,二者皆为异步加载模块。

AMD是前置依赖,在定义模块的时候就要声明其依赖的模块;

CMD是就近依赖,只有在用到某个模块的时候再去require;
在这里插入图片描述

模块(关键字module)

“内部模块”现在称作“命名空间”,“外部模块”现在简称为“模块”;

内部外部为一个相对概念,在ES6和Nodejs中,引入了模块的概念,即一个文件就是一个模块;“内部模块”即当前文件内的模块,“外部模块”即当前文件外的其他模块;

在这里插入图片描述

例如我们在TS工程下新建一个ts文件声明一个变量a,在另一个文件同样声明一个变量a,这时候会出现错误信息:

原因:因为该文件内容是对全局可见的;
解决方案:只需要通过import || export引入模块系统即可;

ES6:(TS也适用)
导出模块:export;(默认导出 export default)
导入模块:import;

CommonJS和AMD:
导出模块:module.exports 或 exports;
导入模块:require( );

注意:

1、module.exports的初始值是一个空对象;在这里插入图片描述
2、exports和module.exports在初始化加载的时候都是指向同一块内存地址的;在这里插入图片描述
在这里插入图片描述

在 Node 中,不能用任何其他对象、函数或变量给 exports 赋值。
例如:
//错误写法 class Currency { } exports = Currency
需要将 exports 换成 module.exports。用 module.exports 可以对外提供单个变量、函数或者对象。
例如
//正确写法 class Currency { } modules.exports = Currency

3、require( )返回的是modul.exports而不是exports;
如果你创建了一个既有 exports 又有 module.exports 的模块,那它会返回 module.exports,而 exports 会被忽略。
module.exports才是真正的接口,exports只不过是它的一个辅助工具。 最终返回给调用的是module.exports而不是exports。

为了支持CommomJS和AMD的exports,TS提供了export=语法:
在这里插入图片描述

动态模块加载(模块只在被需要时加载):

在这里插入图片描述
在这里插入图片描述

外部模块的声明:

在开发过程中我们有时需要引用其他第三方的 JavaScript 的库,虽然通过直接引用可以调用库的类和方法,但是却无法使用TypeScript 诸如类型检查等特性功能。为了解决这个问题,需要将这些库里的函数和方法体的具体实现方法删除后,只保留导出类型声明。我们将所有的这些第三方库的类型声明存放在声明文件中,声明文件以.d.ts为后缀。

例如:
在这里插入图片描述

使用重新导出进行扩展:

在这里插入图片描述

命名空间(关键字namespace)

“内部模块”现在称做“命名空间”;
使用关键字“namespace”,使用export让命名空间里的接口和类暴露出去,不暴露在命名空间外则访问不到。
在这里插入图片描述

命名空间可以分割成多个文件,它们仍属于同一个命名空间,但需要我们加入引用标签(三斜线指令)来告诉编译器文件之间的关联。

编译器会对输入文件进行预处理来解析所有三斜线引用指令,这个过程会以一些根文件开始,它们是在命令行中指定的文件或是在tsconfig.json中的“files”列表里的文件。这些根文件按指定的顺序进行预处理,在一个文件被加入列表前,它包含的所有三斜线引用都要被处理,三斜线引用以它们在文件里出现的顺序,使用深度优先的方式解析。

使用tsc编译时,编译器也会根据代码里引用标签的顺序自动地对输出进行排序。

但使用webpack打包编译ts文件,无法识别三斜线指令,必须使用export与import来导出导入命名空间;

命名空间别名

import q = x.y.z

命名空间和模块

使用命名空间

好处:
结合三斜线指令,使用tsc进行编译,并通过 --outFile将多个文件的同个命名空间结合在一起,再将编译且结合后的js文件通过

缺陷:
在大型应用中,很难去识别组件之间的依赖关系。

命名空间和模块的陷阱:

1、不要使用三斜线指令来引用模块;
在这里插入图片描述

2、不应该对模块使用命名空间

使用命名空间的目的是为了能够将逻辑分组和避免命名上的冲突,模块文件本身已经就是一个逻辑的分组,而且使用模块时的名字也是由导入的时候决定的,所以完全没必要在模块中为导出的对象增加额外的模块层。

不好的例子:
在这里插入图片描述

改进的例子:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值