写点什么

TS 基础之模块化

用户头像
法医
关注
发布于: 1 小时前
TS 基础之模块化

1. TS 中如何书写模块化

TS 中,导入和导出模块,统一使用 ES6 的模块化标准


新建module.ts文件,导出变量name函数numRes


//导出变量name和函数numResexport const name = "法医";
export function numRes(num1:number,num2:number) { return num1 + num2;}
复制代码


新建index.ts文件,用于导入namenumRes


import { name, numRes } from "./myModule";
console.log(name);//输出 “法医”console.log(numRes(1,2));// 打印 3
复制代码


在 TS 中使用模块化是比较简单的,并且我们在导入的时候是不需要自己写import的,可以利用 TS 的智能提示,如下:



想要利用 TS 的智能提示有个前提,那就是在导出文件的时候需要使用普通的导出方式,而不是默认的导出方式,默认导出是没有智能提示的


//普通导出有智能提示export const name = "法医";
export function numRes(num1:number,num2:number) { return num1 + num2;}
//默认导出没有智能提示export default { name: "法医", numRes:function (num1:number,num2:number) { return num1 + num2; }}
复制代码


还有一个点需要注意,就是在导入模块的时候不要加后缀名tsimport { name, numRes } from "./myModule.ts";



之所以会报错,是因为导入模块文件会进行编译,如果存在 ts 后缀名,在编译后的 js 文件中找不到 ts 文件的,所以会报错

2. 编译结果的模块化

TS中使用模块化,有时会使用ES6模块化,有时使用CommonJS模块化,所以也是有必要了解编译后的 JS 使用的是哪种模块化标准。


首先我们应该清楚一点,关于编译结果中的到底使用哪种模块化是可配置的,配置文件是tsconfig.json中的module属性,它就是用来配置编译后的 JS 文件是使用哪种模块化标准的


{  "compilerOptions": {//配置编译选项    "target": "es2016",//编译时用的哪一套ES标准    "module": "es6",//配置编译目标使用的模块化标准,commjs是node环境中的标准,es6也可以    "lib": ["ES2016"],//默认是有dom环境的,但现在用不到,这里面是没有node环境配置的,需要安装第三方库    "outDir": "./dist",//将编译的结果放在哪个目录下面    "strictNullChecks": true,//表示更加严格的空类型检查  },}
复制代码


  • 使用ES6标准对比编译前和编译后

  • es6 模块化导出:


  • 由于在 TS 里面本身使用的是 ES6 的标准,而对编译结果配置的时候也是 ES6 的标准,所以从代码来看,两者没有任何区别的,编译结果只是取消了类型约束。

  • es6 模块化导入:


  • 从代码来看使用 es6 模块导入也是一模一样,没有任何区别的

  • 👉 小知识:

  • 从前后编译的结果来看,当 TS 代码中有注释的时候,编译后的 JS 文件也是会有注释的,如果不希望注释被编译到结果中,此时可以在tsconfig.json进行配置 "removeComments": true,//表示移除注释,配置如下:


    {      "compilerOptions": {//配置编译选项        "target": "es2016",//编译时用的哪一套ES标准        "module": "es6",//配置编译目标使用的模块化标准,commjs是node环境中的标准,es6也可以        "lib": ["ES2016"],//默认是有dom环境的,但现在用不到,这里面是没有node环境配置的,需要安装第三方库        "outDir": "./dist",//将编译的结果放在哪个目录下面        "strictNullChecks": true,//表示更加严格的空类型检查        "removeComments": true,//表示移除注释      },    }
复制代码


  • 使用CommonJS对比编译前和编译后

  • CommonJS 模块化导出:


  • 当我们使用 commonJs 模块化导出的时候,会发现编译后的结果跟编译前有很大差异,在 JS 文件中会发现第一行是use strict严格模式,其实use strict是没必要出现在编译结果中的,因为我们写的 TS 代码本身够严格了,因此我们可以进行配置:


    {      "compilerOptions": {//配置编译选项        "target": "es2016",//编译时用的哪一套ES标准        "module": "CommonJS",//配置编译目标使用的模块化标准,commjs是node环境中的标准,es6也可以        "lib": ["ES2016"],//默认是有dom环境的,但现在用不到,这里面是没有node环境配置的,需要安装第三方库        "outDir": "./dist",//将编译的结果放在哪个目录下面        "strictNullChecks": true,//表示更加严格的空类型检查        "removeComments": true,//表示移除注释        "noImplicitUseStrict": true,//表示编译结果中不包含use strict      },    }
复制代码


接下来我们看这一行代码`Object.defineProperty(exports, "__esModule", { value: true });`这行代码圣骑士相当于`exports._esModule = true;`至于有什么作用这里先不说,一会说。

**CommonJS模块化导入:**
复制代码



在`commonJs`中是没有`import..from..`的,它只能通过`require`方式导入,在编译后的结果里它会自动声明一个变量,也就是上述代码中的`myModule_1`,这个变量是`文件名` + `"_"` + `编号`,如果有多次导入的话,编号会依次自增。
在开发过程中很多时候不需要关心导入导出编译的结果是什么,但是了解这个编译结果对处理细节问题上是有帮助的
总结:
- 如果编译结果的模块化标准是ES6:没有区别- 如果编结果的模块化标准是commonjs:导出的声明会变成exports的属性,默认导出会变成exports的default属性
有的时候我们会遇到比较特殊的情况,比如说我们想使用`node`里面的`fs`,此时会报错,比如说:
![image.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/8b1ebd57ca53424a842de6d164408c0b~tplv-k3u1fbpfcp-watermark.image?)
复制代码

3. 解决默认导入的错误

这一部分研究一下在TS中使用默认导出时产生报错的问题,想要知道什么原因导致的,其实看看编译后的结果也就明白了



从代码中看,fs 提示没有默认导出,这里报错的原因是fs不是通过TS写的,在fs模块里面它是通过module.exports = {}方式导出的,因此导入的时候加一个default,那肯定是不行的,这时候我们可以这么处理:



之所以会产生这么个问题,是因为有些模块不是我们自己写的,我们自己写直接统一使用 ES6 模块就可以了,不会有什么问题,但是以前有些模块使用module.exports = {}方式导出的,这就很尴尬,只能寻找其它解决办法,上述是其中一种办法,但是这种方式不太好,因为fs对象里面不仅仅只有一个函数,有很多,总不能挨个写一遍把,这肯定是太麻烦了,然而我们可以导入所有内容,然后起个别名这种方式处理:



但是对于有强迫症的人来说,我就不想用这种方式,那么还有最后一个办法,在tsconfig.json中配置"esModuleInterop":true,意思是启动 es 模块化交互非 es 模块导出


{  "compilerOptions": {//配置编译选项    "target": "es2016",//编译时用的哪一套ES标准    "module": "CommonJS",//配置编译目标使用的模块化标准,commjs是node环境中的标准,es6也可以    "lib": ["ES2016"],//默认是有dom环境的,但现在用不到,这里面是没有node环境配置的,需要安装第三方库    "outDir": "./dist",//将编译的结果放在哪个目录下面    "strictNullChecks": true,//表示更加严格的空类型检查    "removeComments": true,//表示移除注释    "noImplicitUseStrict": true,//表示编译结果中不包含use strict    "esModuleInterop":true,//启动es模块化交互非es模块导出      },}
复制代码


配置之后,代码不会报错了



😊 好了, 以上就是我的分享,希望小伙伴们点赞 👍 支持一下哦~ 😘,我会更有动力的 🤞


发布于: 1 小时前阅读数: 4
用户头像

法医

关注

公众号@前端猎手 2020.07.17 加入

我是法医,一只治疗系前端码猿🐒,与代码对话,倾听它们心底的呼声,期待着大家的点赞👍与关注➕。 [微信:wKavin]

评论

发布
暂无评论
TS 基础之模块化