先看:ES6 模块(重点)
教程中的复合写法,有个地方不太明白,模块转发的时候使用
export { default } from "foo"
,但是下面又提到一种办法,export someIdentifier from "someModule";
两个方法有点重了。。。
ES6 模块导入和导出,我们使用 NodeJs 来调试,虽然 Node.js
已经实现了 99% 的 ES6 新特性,不过现在无法支持 ES6 的导入导出模块,但在 Node 9 中提供了一个尚处于 Experimental 阶段的模块,即把 .js
文件改成 .mjs
可直接在 Node 环境下使用 import/export。运行的时候使用命令行内容为:node --experimental-modules b.mjs
- 变量导出
export const name = "Condor Hero";
export var sex = "girl";
- 变量汇总导出
const name = "lili";
const sex = "girl";
export { name , sex };
- 重命名导出
const age = 19;
export { age as nianling };
研究下面的写法:具名暴露与默认暴露的转换
const age = 19;
export { age as default };//等同于 export default age;
import age from "./b.mjs";
console.log(name);
- 导出函数和类
export function main(){}
export class A {}
- 模块引入
//引入1
import sex from "./a.mjs";
//引入2
import { age } from "./a.mjs";
console.log(age);
//混合引入
import sex , { age } from "./a.mjs";
- 重命名模块引入
import * as A from "./a.mjs";
console.log(A.age);
- 模块默认导出和引入
//导出
export default class A {}
//导入
import A from "./a.mjs";
console.log(A);
//重命名导入
import * as B from "./a.mjs";
console.log(B);
- 复合写法
a=>b=>c ,c 模块会使用到 a 模块的内容,同时需要 b 模块进行周转,b 模块的内容就可以使用复合写法。
//a.mjs
export function fun(name){
console.log(name);
}
//b.mjs
// // 正常写法
// import { fun } from "./a.mjs";
// export { fun };
//复合写法
// export { fun } from "./a.mjs";//暴露部分
// 还可以使用*代替导出
export * from "./a.mjs";//全部暴露出去
//c.mjs
import { fun } from "./b.mjs";
console.log(fun("Condor Hero"));
- 动态引入
import 大多数都是作为静态引入使用的,但是有时也可以作为方法使用,动态引入内容,默认返回 promise。
//a模块的内容
console.log(1111)
export const name = "Condor Hero";
export default "a";
//b模块的内容
console.log(2222)
export default "b"
//c模块的内容
let state = true;
if(state){
import("./a").then(res=>console.log(res.name,res.default));
}else{
import("./b");;
}
- 内容注入
//只注入模块里面的内容
import "./a.mjs"
//和NodeJs下面这个写法差不多
require("./a");
在模块化开发过程中,如果需要注入 css 我会尝试使用此方法:
import "css.css";
import "less.less";
import "scss.scss";
NodeJs 符合 CommonJS 的标准:
默认暴露
module.exports = "默认暴露";
var a = require("./b");
console.log(a);
单个暴露
exports.a = 10;
var obj = require("./b");
console.log(obj.a);
TypeScript 的模块化时完全继承 ES6 ,也就是将 ES6 的东西 TypeScript 都能够使用,除此之外还稍微兼容了下 CommonJS 的标准唯一的不同就是export = 和 import = require()
语法。
//a模块
export = 10;
//b模块
import a = require("./b");
console.log(a);//10
这样的话,如果我们使用 TS 引用第三方模块就有三种写法,这里以 dayjs 为例,先安装:
npm i -D dayjs
dayjs 和 moment API 和 功能差不多,但是大小只有仅仅有 2kb 左右。
// import dayjs from "dayjs";
import dayjs = require("dayjs");
console.log(dayjs(new Date()).format("YYYY-MM-DD"));//2020-02-02
import * as dayjs from "dayjs";//第三种
console.log(dayjs.default(new Date()).format("YYYY-MM-DD"));
二、命名空间(有模块就不用命名空间了)
关于术语的一点说明: 请务必注意一点,TypeScript 1.5里术语名已经发生了变化。 “内部模块”现在称做“命名空间”。 “外部模块”现在则简称为“模块”,这是为了与 ECMAScript 2015里的术语保持一致,(也就是说
module X {
相当于现在推荐的写法namespace X {
)。
翻一下上面的话:一个文件就是一个模块, “内部模块”就是文件里面,是我们写代码的地方,为了防止可能出现命名冲突,出现了命名空间,防止程序员命名冲突,“外部模块”就是一个文件。以前 TypeScript 把命名空间写成 module X{}
module 英文就是模块的意思,为了防止与 ES6 冲突特地改成命名空间(namespace)。看例子:
一个文件里面我定义了一些东西:
class People { };
const height:number = 180;
function main():void{};
如果又需要在这个文件里面定义同样的变量或类,就会产生命名冲突,或者是多人开发没注意在同一个文件里面定义了同样的东西。怎么办?(命名空间不常用的原因就在这,这些问题完全可以很方便的人为避免掉,或者使用模块更加方便)
namespace A {
class People { };
export const height:number = 180;
export function main():void{};
}
console.log(A.People);
namespace
一般配合 export
一起使用。命名空间里面的内容必须通过 export
才能被访问到。
如果想把命名空间引入到另一个文件里面,一般使用模块来实现。
//a.ts
export namespace A {
export class People { };
export const height:number = 180;
export function main():void{};
}
//b.ts
import { A } from "./a";
console.log(A.People);
但是官方却推荐使用三斜线指令语法,其实都多文件了使用了,当然是模块化来实现了使用三指令有点多余还麻烦。
//a.ts
namespace A {
export class People { };
export const height:number = 180;
export function main():void{};
}
//b.ts
/// <reference path="./a.ts" />
console.log(A);
程序不能立刻执行,否则会报错,因为要确保所有编译后的代码都被加载了,所以需要把所有的输入文件编译为一个输出文件,使用 --outFile 实现:
tsc --outFile sample.js b.ts
这时程序才能正常执行。
这里还有一个知识点,简化的命名空间的操作,任何的标识符都可以创建别名得到一个短的名字。其实就和 var 赋值没啥不同,语法:import q = x.y.z
。
//a.ts
// namespace A {
// export class People { };
// export namespace B {
// export let sex:string = "girl";
// }
// };
//b.ts
/// <reference path="./a.ts" />
import C = A.B;
console.log(C);
注意命名空间可以嵌套使用