在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
首先es和cmj大家都知道不一样,具体区别也就不多说,需要注意的是TS的模块也是自己实现的,不过在ES Module 2015(es6)定稿下来后,TS沿用和支持了ES module,不过TS除了使用ES module的规范,自己也有一套namespace的模块管理,这在某个版本前一直用namespace管理模块,直到后来和ESM保持一致才有改动。例如下面官网说法:
注意babel是典型的ES module写法,babel本身就是将ES6,ES7的高级语法转为浏览器能读取的代码,babel项目迁移到ts,才会出现一些模块写法不兼容的问题。(react+ts项目中代码的转义是靠webpack的babel-loader来转义tsx,ts语法,babel-loader真强大,TS语法,类型的提示和校验则是靠ForkTsCheckerWebpackPlugin,TsconfigPathsPlugin,eslint等插件去完成) TS中常常用import * as React 导入。TS 把 CJS 模块作为一个 Namespace 导入,所以,为了解决上面提到的报错,需要这样导入 CJS 模块,以及任何没有 default 导出的模块: import * as React from 'react' 这样子的代码,如果从 babel 迁移到 TS 就需要大幅的改动代码,不过 TS 也注意到了这个问题,添加了一个 compile option 支持 babel 的这种写法 esModuleInterop, PR 在下面 https://github.com/Microsoft/TypeScript/pull/19675 // tsconfig.json 在该选项中,所有 ES Module 文件会导出一个名为 __esModule 的隐藏属性,值为 true。对于导入 ES Module 时,所有行为没有变化。 整体导入其它模块(import * as ns)时,若不是 ES Module,则将导出内容本身作为模块的 default 属性,并将其它所有属性原样拷贝到模块中。
即module.export导出的模块,和其他挂载在exports上的属性,都会拷贝到* as obj的obj这个对象寄来,且执行obj.foo === 'foo' 为true,obj.default()则为打印foo,此时和es module的import 就表现一致了,导入的模块对象中default key为es module中default导出的或者cmj module.export导出的,其他属性则为es module 正常export的和cmj中挂载在exports的属性。 而默认导入模块(import name)时,既然普通的module.export导出的内容视为default,那么TS导入就也是import xxx(随便起) from 'xxxx'; 但是注意使用babel的项目,比如TS+react,使用的bable-loader,我发现上面的代码obj只会打印出module.export导出的属性,即只打印() => { 这里只对ts内置的模块转换做研究,后续有时间可以再对bable的多模块系统交互转换做点研究和实践。 TS中相应的源码处理工具函数为:
TypeScript 改善了 ES Module 与 CommonJS 的交互支持,但在实际项目还是用的比较少,tsc命令只有在node+ts项目中可能遇到,而且这种项目大家也有用ts-node来运行的,大多数项目,现在的主流ts+react,ts+vue等前端工程化项目,都是在可能的情况下使用 JavaScript 打包工具(webpack等中的一些loader和插件)处理可以避免不必要的运行时开销和不确定行为。 ES6的import函数es6新增了动态引入模块的import()函数,传参和import关键字一样,只是是在运行时确定,可以再if语句中使用(import关键字不可以,因为在编译时(会被 JavaScript 引擎静态分析)就会先于其他代码执行,所以放在代码块中无意义,只能放在模块的顶层,而来就加入了import()函数,类似node的require函数,都是运行时确定,即什么时候运行到这一句,也会加载指定的模块。另外,import()函数与所加载的模块没有静态连接关系,这点也是与import语句不相同。(import关键字有时候也叫"连接")。 import()就很像Node 的require方法,区别主要是前者是异步加载,后者是同步加载。 import返回的是promise对象,即也可在await块中使用。 |
请发表评论