浅谈TypeScript的模块导入导出
0. 写在前面
Typescript这语言吧,整体来讲设计的还不错,就是这个导入导出语句的复杂程度,实在令人吃惊,一个简单的外部引用模块,为啥能把语句搞的这么复杂,纵然有历史兼容的原因,总归还是设计的锅。
1. 最常见的导出导入
最常见的导出分两种,一种是先声明完再导出,一种是在声明时导出。
1.1 先声明再导出
导出语句是
export {something1, something2}
,花括号中的something就是我们要导出的变量/类/函数或其他数据类型,如果有多个要导出的内容,就用逗号隔开。
// OnlyOneEarth.ts
class Earth{
name: string = 'earth';
rotation(){
let oneday: string = 'A rotation takes 24 hours.';
console.log(oneday);
let human: string = 'Human being lives on Earth.';
export {Earth, human};
1.2 在声明时导出
声明时导出不用花括号,直接在声明语句最前边加上
export
关键词就行。
// ExploringMars.ts
export class Mars{
name: string = 'Mars';
status: string = 'China will explore Mars in the following several decades.';
export function exploring(){
console.log('Launching Changzheng-5 rocket.');
console.log('Add oil, 胖五.');
1.3 导入
如果要将上面的导出语句导出的内容导入到文件中,对应的导入语句是
import {something1, something2} from 'modulename'
,something是我们要导入的变量/类/函数或其他数据类型,有多个要导入的内容就在花括号中用逗号隔开,modulename则是上面导出的模块名,一般是文件名,注意模块名前的
./
是必须的,代表当前文件夹下,如果是其他文件夹就制定为其他路径。
// SolarSystem.ts
import {Earth, human} from './OnlyOneEarth'
import {Mars, exploring} from './ExploringMars'
let ourEarth: Earth = new Earth();
let mysteriousMars: Mars = new Mars();
console.log(human);
console.log(mysteriousMars.status);
ourEarth.rotation();
exploring();
2. 奇奇怪怪的default导出导入
导出导入有个奇怪的选项,就是默认导出和默认导入。默认导出有个奇怪的特性,每个模块文件只能有一个默认导出语句,也就是说,只能用一次
export default {something1, something2, ..., somethingN}
语句,bwt,如果只有一个导出内容,something是可以不用花括号括起来的。
// Jupiter.ts
class Jupiter{
name: string = 'Jupiter';
feature: string = 'very very big.';
let jupiterStatus: string = 'Jupiter is absorbing material from the sun.';
export default {Jupiter, jupiterStatus};
导入时,同样比较特别,我们不需要关注导出的内容原本的名字是些什么,只要记住相关的原模块用于
from
,然后就用一个我们喜欢的新模块名给它重命名。
// NASA.ts
import SpectacularJupiter from './Jupiter'; // 这里SpectacularJupiter相当于Jupiter和jupiterStatus的集合体
let beautifulJupiter = new SpectacularJupiter.Jupiter();
console.log('NASA report: ' + beautifulJupiter.name + ' is ' + beautifulJupiter.feature);
console.log(SpectacularJupiter.jupiterStatus);
上面的
SpectacularJupiter
就是我们按自己喜好起的一个模块名字,它代表从
Jupiter.ts
模块导入的
Jupiter
类和jupiterStatus的集合体,也就是模块。
3. 便捷的整体导入
Typescript提供了一次性导入所有内容的方法:
import * as 'theNameYouLike' from 'modulename
,其中
*
号代表所有内容,然后将所有导入内容合并到
theNameYouLike
变量中,
modulename
依然是模块名字。
// CNSA.ts (China National Space Administration)
import * as PECplan from './ExploringMars'
PECplan.exploring();
PEC is the abbreviation of 「Planetary Exploration in China」.
https://zh.wikipedia.org/wiki/%E4%B8%AD%E5%9B%BD%E8%A1%8C%E6%98%9F%E6%8E%A2%E6%B5%8B%E4%BB%BB%E5%8A%A1
4. 无法理解的重新导出
重新导出这个功能光看名字实在难以理解,其实它的作用主要是在一个模块中导出另一个模块的内容,官方将这种操作称为“扩展模块功能”,使用语句:
export {something} from 'anothermodule'
。这里需要说明一下,在a模块中利用重新导出语句将b模块的部分内容导出,并不会使得b模块内容被import到a模块中。
// Moon.ts
class Moon{
name: string = 'Moon';
revolution(){
let oneMonth: string = 'The time of revolution of Moon around the earth is a month.';
console.log(oneMonth);
export {Moon};
export {Earth} from './OnlyOneEarth' // 注意,只有OnlyOneEarth本身也是模块时,才可以这样写from,要
// 使一个文件变成一个模块,则该文件中必须有export语句,换言之,
// 有export语句的文件才是模块
如果要一次导出所有内容,可以使用:
export * from './OnlyOneEarth'
5. 给导出或导入的内容重命名
前面讲了一些基础的导出导入方式,但还没涉及到将内容重命名的方法,没错,我们是可以将导出或者导入的内容按自己喜好给重命名的,需要的只是在导出或导入时加上一个关键词
as
。
5.1 导出
// ParallelEarth.ts
class ParallelEarth{
name: string = 'parallel_earth';
feature: string = 'If parallel universe is exist, the parallel earth will also exist.'
export {ParallelEarth as AnotherEarth}
export {Earth as OriginEarth} from './OnlyOneEarth'
5.2 导入
// ParallelSolarSystem.ts
import {OriginEarth as FirstEarth} from './ParallelEarth' // 注意,OriginEarth是从ParallelEarth.ts模块中导出的,所以这里不能从OnlyOneEarth.ts模块导入
import {AnotherEarth as SecondEarth} from './ParallelEarth'
let earth1 = new FirstEarth();
let earth2 = new SecondEarth();
earth1.rotation();
console.log(earth2.feature);
6. 兼容CommonJS和AMD规范的导入导出
CommonJS和AMD是两个不同的JS模块规范,CommonJS应用于浏览器端,AMD适用于服务器端,Typescript为了兼容这两个规范,又引入一种导入和导出模块的方式。
导出:
export = 'something'
导入:
import 'theNameYouLike' = require('modulename')
// Saturn.ts (土星)
class Saturn{
name: string = 'Saturn';
feature: string = 'Saturn has a beautiful and big ring.'
function shining(){
let ring: string = 'Saturn has a 3 meter-thick shining ring.'
console.log(ring);
export = {Saturn, shining}; // 只能有一句export =语句,所以多个导出内容要放在花括号中隔开,只有一个内容时可以去掉花括号
然后是导入:
// Voyager1.ts (旅行者1号)
import SoilPlanet = require('./Saturn'); // SoliPlanet相当于Saturn和shining的集合体
let soilplanet = new SoilPlanet.Saturn();
let historicalMoment: string = 'Voyager1 visited ' + soilplanet.name + ' in 1980.';
console.log(historicalMoment);
SoilPlanet.shining();
7. 总结
7.1 常见的导出语句:
// 普通导出
export {something1, something2, ..., somethingN};
export {something1 as rename1, something2 as rename2, ..., somethingN as renameN};
export let something = '100';
export function func(){/* some actions here */};
// 默认导出
export default something;
export default {something1, something2, ..., somethingN};
export default let something = '100';
export default function func(){/* some actions here */};
// 重新导出
export {something1, something2, ..., somethingN} from 'modulename';
export {something1 as rename1, something2 as rename2, ..., somethingN as renameN} from 'modulename';
export * from 'modulename';
// 兼容CommonJS和AMD的导出
export = {something1, something2, ..., somethingN};
export = something;
7.2 常见的导入语句:
// 普通导入
import {something1, something2, ..., somethingN} from 'modulename';
import {something1 as rename1, something2 as rename2, ..., somethingN as renameN} from 'modulename';
// 默认导入
import theNewModuleNameYouLike from 'modulename';