爲 Vue3 學點 TypeScript, 什麼是命名空間(namespace)

往期目錄

第一課, 體驗typescriptjavascript

第二課, 基礎類型和入門高級類型vue

第三課, 什麼是泛型?java

第四課, 解讀高級類型git

第五課, 什麼是命名空間(namespace)?github

何時要用命名空間?

若是你發現本身寫的功能(函數/類/接口等...)愈來愈多, 你想對他們進行分組管理就能夠用命名空間, 下面先用""舉例:typescript

namespace Tools {
    const TIMEOUT = 100;

    export class Ftp {
        constructor() {
            setTimeout(() => {
                console.log('Ftp');
            }, TIMEOUT)
        }
    }

    export class Http {
        constructor() {
            console.log('Http');
        }
    }

    export function parseURL(){
        console.log('parseURL');
    }
}

仔細看你會發現namespace下還有export, export在這裏用來表示哪些功能是能夠外部訪問的:segmentfault

Tools.TIMEOUT // 報錯, Tools上沒有這個屬性
Tools.parseURL() // 'parseURL'

最後咱們看下編譯成js後的代碼:函數

"use strict";
var Tools;
(function (Tools) {
    const TIMEOUT = 100;
    class Ftp {
        constructor() {
            setTimeout(() => {
                console.log('Ftp');
            }, TIMEOUT);
        }
    }
    Tools.Ftp = Ftp;
    class Http {
        constructor() {
            console.log('Http');
        }
    }
    Tools.Http = Http;
    function parseURL() {
        console.log('parseURL');
    }
    Tools.parseURL = parseURL;
})(Tools || (Tools = {}));

看js代碼能發現, 在js中命名空間其實就是一個全局對象. 若是你開發的程序想要暴露一個全局變量就能夠用namespace;ui

如何用命名空間來管理類型?

命名空間不只能夠用在邏輯代碼中, 也能夠用在類型, 用來給類型分組:this

namespace Food {
    export type A = Window;
    export interface Fruits{
        taste: string;
        hardness: number;
    }

    export interface Meat{
        taste: string;
        heat: number;
    }
}

let meat: Food.Meat;
let fruits: Food.Fruits;

如何引入寫好的命名空間?

有2種方式, 一種/// <reference path="xxx.ts" />, 還有就是import:

經過 "/// <reference path='xxx.ts'/>" 導入

經過reference進行導入至關於xxx.ts文件內的命名空間和當前文件進行了合併:

xxx.ts
// xxx.ts
namespace Food {
    export interface Fruits{
        taste: string;
        hardness: number;
    }
}
yyy.ts
// yyy.ts
<reference path="xxx.ts" />

let meat: Food.Meat;
let fruits: Food.Fruits;

如今在yyy.ts中咱們就能夠直接使用xxx.ts中的Food類型了, 而不須要使用import.

經過import導入

若是命名空間是用export導出的, 那麼使用的時候就不能夠用/// <reference/>了, 要用import導入:

xxx.ts
// xxx.ts
// 使用export導出
export interface Fruits{
    taste: string;
    hardness: number;
}

export interface Meat{
    taste: string;
    heat: number;
}
yyy.ts
// yyy.ts
import {Food} from './xxx'; // 使用import導入
let meat: Food.Meat;
let fruits: Food.Fruits;

如何合併多個命名空間

咱們知道接口是能夠合併的, 命名空間也是能夠的, 下面咱們把Vegetables類型合併到Food類型中:

xxx.ts
// xxx.ts
namespace Food {
    export interface Fruits{
        taste: string;
        hardness: number;
    }
}
yyy.ts
// yyy.ts
<reference path="xxx.ts" />
namespace Food {
    export interface Vegetables{
        title: string;
        heat: number;
    }
}

type Vh = Food.Vegetables['heat'] // number;

export=

若是你的tsconfig中設置了"module": "umd",, 那麼export = Food等價於export default Food, export=常見於支持umd的插件的聲明文件.

命名空間在lodash裏的應用

其實咱們看下那些老牌插件(jq/lodash)裏使用namespace特性的代碼, 能夠發現主要是在聲明文件中(xxx.d.ts), 用來表示暴露出來的全局變量(好比lodash的"_").

關於聲明文件

上面爲了解釋命名空間說起了聲明文件(xxx.d.ts), 但因爲聲明(declare)的內容不少, 因此我會在下一節詳細介紹.

總結

其實若是你的項目直接是用ts寫的可能用不上namespace, 畢竟export就能夠產生模塊, 模塊自然就有隔離分組做用.

能力有限, 若是路過大神看到不對的地方還請多多指點, 我必虛心接受.

最後建議你們多寫多練, 祝你們早日上手ts, 放幾個我用ts寫的項目當作參考, 拋磚引玉, 加油!

手勢庫, 支持點擊/拖拽/旋轉/縮放: https://github.com/any86/any-...

爲vue組件生成this.$xxx的命令: https://github.com/any86/vue-...

相關文章
相關標籤/搜索