typescript 内部模块-TypeScript 的模块和命名空间

2023-09-01 0 4,157 百度已收录

模块

●前言:

JavaScript 在 ES2015 中引入了模块的概念,我们的 JS 也开始经历标准的模块化开发阶段,而这个概念在 TS 中也得到了继承。

TS中,从句型到概念,与JavaScript中基本相同

●因为我们主要学习TS,所以这里对模块的句型和概念进行简单的准备。

出口

●在一个文件中,可以使用export关键字导入所有声明

●实际上,内容是暴露给外界并被其他模块使用的。

基本导入

●moduleA.ts
// 导出一个变量
export const num = 100
export const str = 'hello world'
export const reg = /^千锋教育$/
// 导出一个函数
export function fn() {}
// 导出一个类
export class Student {}
export class Person extends People {}
// 导出一个接口
export interface Users {}

重新进口

●有时我们可能会导出文件中的一段内容,然后再次导入

●modeuB.ts

export * from './moduleA'

○将moduleA文件的所有内容导出到此moduleB文件中

○ 并在 moduleB 中进行了导入

●很多朋友可能会问,这有什么意义呢?

○ 其实有些模块是可以合并的

●举个例子

○模块A.ts

export const num = 100

○模块B.ts

export const str = 'hello world'

○模块C.ts

export interface Users {}

○moduleIndex.ts

export * from './moduleA'
export * from './moduleB'
export * from './moduleC'

typescript 内部模块-TypeScript 的模块和命名空间

○这样就相当于使用moduleIndex文件将以下三个模块集成导入为一个

导出重命名

●有时,我们重新导入时,可能会遇到多个模块重名的问题

●也就是说,你可能会遇到多个模块不是一个人写的,导致模块命名风格不一致。

●我们写入的时候导入的时候可以重命名

●语法

export { num as current } from './moduleA'

○相当于导出该文件中的moduleA模块中的num数据

○ 并重新进口

○只是再次导入时,使用的名称是当前的。

● 举一个反例

○模块A.ts

export const n = 100

○模块B.ts

export const s = 'hello world'

○模块C.ts

export interface Aaa {}

○moduleIndex.ts

export { n as num } from './moduleA'
export { s as str } from './moduleB'
export { Aaa as Users } from './moduleC'

○这样就相当于使用moduleIndex文件将以下三个模块集成导入为一个

○并且上述三个模块导入的内容已更名

○ 相当于

// 伪代码, 仅仅为了直观看一下上面代码的效果
export const num = 100 // moduleA 中导出的 n
export const str = 'hello world' // moduleB 中导出的 s
export interface Users {} // moduleC 中导出的 Aaa

进口

●与以往进口配套

基本导出

●直接导入模块的某些或个别内容

● moduleA.ts => 导入

export function study () {}
export function play () {}
export function sleep () {}

●index.ts => 用于导出

import { study, play } from './moduleA'

导入重命名

●导入时,有时我们可能不想在原始文件中使用导入的名称。

●无论是因为命名冲突还是因为原来的名称太长,都有可能。

●然后我们就可以进行重命名操作了

● moduleA.ts => 导入

export function study () {}
export function play () {}
export function sleep () {}

●index.ts => 用于导出

import { study as s } from './moduleA'

○相当于在moduleA中导入一个study方法

○但是在索引文件中使用时,使用函数名s

默认导入

●每个模块都会有一个默认导入,使用default即可

●注意:一个模块只能有一次默认导入

●moduleA.ts

const utils = {
    study () {},
    play () {},
    sleep () {}
}
export default utils

○这是默认导入方式下moduleA导入的utils对象。

● 索引.ts

import XhlUtils from './moduleA'

○这里索引中的XhlUtils获取的是moduleA文件中导入的utils对象。

模块化兼容

●前面的都是JS的模块句型。 我们相当于准备考试或者复习

●现在这块是TS对模块化的改进,大家要注意学习

typescript 内部模块-TypeScript 的模块和命名空间

前言:

虽然我们刚才说的是ES6 Module的句型规范

但我们知道,在JS的开发过程中typescript 内部模块,我们并不是唯一的模块化语句规范

我们还有 AMD/CommonJS/UMD 等模块化句子规范

每个都有自己的导出和导入句型规范

但这些句型中有一个共同的规范,那就是exports变量的出现

导出变量

CommonJS 和 AMD 中都有一个导出对象

是这两个模块化规范的默认导入,相当于ES6模块化规范中的默认导出

虽然你们的句型相似,意思也相似

但ES6模块化句型不兼容CommonJS和AMD语法规范

因此,TS中对ES6的模块句型进行了一些扩展

编译时可以更好的支持CommonJS句型

出口=

●如果你只是用TS做后端开发,不需要考虑模块化句型的兼容性typescript 内部模块,那么你就不需要理解这个

● 仅当需要兼容CommonJS和AMD语法时

●那么我们的导出默认就不能用了

●index.ts => 不考虑兼容性

class Person {}
export default Person

●index.ts => 考虑兼容性

class Person {}
export = Person

导入 = 要求('')

●为了支持兼容性,我们的导入句型发生了变化,所以我们的导出句型也会发生变化

●index.ts => 不考虑兼容性

import Person from './xxx'

●index.ts => 考虑兼容性

import Person = require('./xxx')

typescript 内部模块-TypeScript 的模块和命名空间

编译结果

●如果按照兼容的形式写导入内容,会编译成以下情况(看一下)

○简单模块

import Person = require('./xxx')

○AMD(需要JS)

define(["require", "exports", "./xxx"], function (require, exports, mod_1) {
    console.log(mod_1)
});

○CommonJS(节点)

const Person = require('./xxx')

○UMD

(function (factory) {
    if (typeof module === "object" && typeof module.exports === "object") {
        let v = factory(require, exports); if (v !== undefined) module.exports = v
    }
    else if (typeof define === "function" && define.amd) {
        define(["require", "exports", "./xxx"], factory)
    }
})(function (require, exports) {
    let Person = require("./xxx")
    console.log(Person)
});

○系统简单模块

System.register(["./xxx"], function(exports) {
    let Person
    return {
        setters: [
            function (param) {
                Person = param
            }],
        execute: function() {
            console.log(Person)
        }
    }
})

○原生ES6模块

import Person from './xxx'

命名空间

前言:

最早的TS中,没有命名空间的概念,而是模块化的概念

分为内部模块和外部模块两种

从TS1.5开始,内部模块被重命名为命名空间,所以虽然命名空间是内部模块

那么我们如何区分它们呢? 其实我们主要是从内部包装的内容来区分。

命名空间(模块内部):主要用于组织代码,避免命名冲突

外部模块(module):注重代码封装和复用,一个模块可能包含多个命名空间

例子

●我们开发过程中,如果一个ts文件没有写模块化句型

●则默认该文件中定义的所有变量都被全局挂载。

●那么两个文件中不能有重复的变量名,否则会出现问题

●a.ts

const num = 100
const str = 'hello world'

●b.ts

const num = 200

●这两个文件看似无关,但它们都包含num变量。

●但是由于没有模块句型,所以这两个是全局挂载的变量。

●这时候我们可以把这个内容放到命名空间(内部模块)中来解决这个问题

命名空间

●语法:

namespace 命名 {
    /* ... */
}

●变量可以在命名空间内定义和使用,内容也可以暴露给外界。

●暴露命名空间内的内容也使用export关键字

namespace GoodsHandler {
  const current = 1
  const pagenum = 10
  const info = []
  export const list = info.slice((current - 1) * pagenum, current * pagenum)
}

○这样我们所有的内容就都放在这个名为GoodsHandler的命名空间中了

○其中三个变量不能在其他地方使用,只能在当前命名空间内使用。

○向外界曝光了一个名为list的内容

引入命名空间

●当我们需要使用命名空间时,可以使用三斜杠(///)命令

●注意:文件开头必须使用三斜杠(///)命令

/// <reference path="./goodsHandler.ts" />
console.log(GoodsHandler.list)

模块和命名空间

●当我们使用模块和命名空间来组织我们的代码之后

●我们向外界暴露的内容越来越多,我们也会考虑文件过多的问题。

●所以有时我们可以将命名空间和模块一起使用

●即一个模块内,可以导入多个命名空间

●功能与概念的区分

○命名空间:主要解决变量命名冲突

○模块:组织代码、复用

export namespace GoodsHandler { /* ... */ }
export namespace ListHandler { /* ... */ }

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悟空资源网 typescript typescript 内部模块-TypeScript 的模块和命名空间 https://www.wkzy.net/game/186245.html

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务