昨天學習了如何建立 React 加 TypeScript 的開發環境,但是在嘗試開發的過程中,發現還有一些很重要的觀念需要了解,模組就是其中之一。在 React 專案中大量使用模組的概念,每個檔案都可視為一個模組,進行匯入(import)和匯出(export)。
在 ES6 之前,JS並沒有原生的模組機制,直到 ES6 引進 Module,TS 目前也沿用支援模組。
假設沒有模組,預設情況下我們寫的 TS 程式碼會在全域範圍內,如果在一個專案中有多個.ts檔案,則在某一檔案中宣告的變數或函式,其他檔案可以調用。
例如,專案中有兩個 TS 檔案:file1.ts 和 file2.ts
var greeting : string = "Hello World!";
console.log(greeting); //Prints Hello World!
greeting = "Hello TypeScript"; // OK
但這樣其實很危險,在 file1.ts 中的宣告變數 greeting 也可以在 file2.ts 中調用甚至修改。任何人都可以輕易修改在全域範圍內宣告的變數,因為非常容易造成程式碼的衝突或錯誤。
有了模組機制後,每個 Module 可以自成獨立的 Scope,各 Module 可自由定義變數、型別,要開放外界存取的項目再透過 export 開放,而當需要引用其他 Module 時,則必須明確使用 import 匯入才能使用。如此,各 Module 可以獨立開發維護不彼此干擾,甚至能實現需要時再動態載入,大幅提升開發及應用彈性。
有了模組後,上面的程式碼就可以修改如下:
export let greeting : string = "Hello World!";
console.log(greeting); //Error: cannot find 'greeting'
由於在 file1 變數前加上了 export,形成了模組 ,這時候 file2 無法直接調用 file2 就會報錯。
在單獨的.ts檔案中定義模組,該檔案可以包含函式、變數、介面和類別,使用export
關鍵字導出,舉例來說:
export let age : number = 20;
export class Employee {
empCode: number;
empName: string;
constructor(name: string, code: number) {
this.empName = name;
this.empCode = code;
}
displayEmployee() {
console.log ("Employee Code: " + this.empCode + ", Employee Name: " + this.empName );
}
}
let companyName:string = "XYZ";
在上面的範例中包含了兩個變數和一個類別模組。變數 age 和 Employee 類別使用 export 前綴進行導出,但 companyName 變數沒有,因此,其他檔案是無法調用companyName的。
當使用關鍵字 import 導入模組,該檔案就可以使用該模組,語法如下:
import { 導出模組名稱 } from "檔案路徑"
有不同種導入模組的方式:
import { Employee } from "./Employee";
let empObj = new Employee("Steve", 1);
empObj.displayEmployee(); //Employee Code: 1, Employee Name: Steve
上面導出了類別 Employee,這邊則將單一模組 - 類別 Employee導入進來做使用。
import * as Emp from "./Employee"
console.log(Emp.age); // 20
let empObj = new Emp.Employee("Bill Gates" , 2);
empObj.displayEmployee(); //Output: Employee Code: 2, Employee Name: Bill Gates
上面的程式碼,我們使用 * 將 .Employee 檔案中的所有模組(也就是 age 變數和 Employee類別)都導出,並命名為變數 Emp 一起導入,這時候就可以以使用 Emp.age 和 Emp.Employee。
import { Employee as Associate } from "./Employee"
let obj = new Associate("James Bond" , 3);
obj.displayEmployee();//Output: Employee Code: 3, Employee Name: James Bond
這裡在導入時只將Employee類別導入,但導入時使用 as 命名為Associate,增加可讀性或賦予名稱意義
現在,已經知道如何在.ts檔案中定義模組(如果之前有寫作 React 專案的人,會發現其實是一樣的,就當做複習吧!)但要使用仍然需要編譯成.js檔案。TS 模組編譯會比較複雜,目前有各種規範像是:AMD、CMD、closure、CommonJS、ES6等等,百家爭鳴,TS 編譯設定也可指定要用哪一種規範進行編譯。
今天是放假日,小小偷懶一下,先探討到這裡,複習一下 React 專案中的導出(export)和導入(import),關於模組編譯部分就留待明天的文章繼續吧,明天見囉!