[关闭]
@darktutu 2015-05-22T10:57:00.000000Z 字数 3962 阅读 2350

TypeScript - Modules

TypeScript


这篇文章概括了在TypeScript中使用模块组织代码的各种方法。我们将包括内部模块和外部模块以及讨论如何恰当使用他们。我们还会介绍一些外部模块的进阶使用,并且指出一下在使用中常见的错误。

第一步

接下来从我们全篇都会使用的程序开始。我们写过一个小型的字符串验证程序,可以用来验证网页上用户输入的内容或者外部文件的数据格式。

  1. interface StringValidator {
  2. isAcceptable(s: string): boolean;
  3. }
  4. var lettersRegexp = /^[A-Za-z]+$/;
  5. var numberRegexp = /^[0-9]+$/;
  6. class LettersOnlyValidator implements StringValidator {
  7. isAcceptable(s: string) {
  8. return lettersRegexp.test(s);
  9. }
  10. }
  11. class ZipCodeValidator implements StringValidator {
  12. isAcceptable(s: string) {
  13. return s.length === 5 && numberRegexp.test(s);
  14. }
  15. }
  16. // Some samples to try
  17. var strings = ['Hello', '98052', '101'];
  18. // Validators to use
  19. var validators: { [s: string]: StringValidator; } = {};
  20. validators['ZIP code'] = new ZipCodeValidator();
  21. validators['Letters only'] = new LettersOnlyValidator();
  22. // Show whether each string passed each validator
  23. strings.forEach(s => {
  24. for (var name in validators) {
  25. console.log('"' + s + '" ' + (validators[name].isAcceptable(s) ? ' matches ' : ' does not match ') + name);
  26. }
  27. });

模块化

随着更多的验证器的添加,我们需要某种组织方案,以便我们能够很好的跟踪我们的类型,并且不需要担心和其他对象名字的冲突。现在我们把对象封装到Modules中来替代向全局的命名空间中添加大量的名字。

在例子中,我们把所有validator相关的类型移入Validation 的module中。因为我们需要在外部访问module中的类和接口,所以我们在他们前面加上了export。相反的,变量lettersRegexpnumberRegexp是内部实现逻辑,所以它们没有被输出这样就无法在外部访问到它们。在测试代码底部,我们现在需要通过名称来从外部访问module中的类型Validation.LettersOnlyValidator等。

Modularized Validators

  1. module Validation {
  2. export interface StringValidator {
  3. isAcceptable(s: string): boolean;
  4. }
  5. var lettersRegexp = /^[A-Za-z]+$/;
  6. var numberRegexp = /^[0-9]+$/;
  7. export class LettersOnlyValidator implements StringValidator {
  8. isAcceptable(s: string) {
  9. return lettersRegexp.test(s);
  10. }
  11. }
  12. export class ZipCodeValidator implements StringValidator {
  13. isAcceptable(s: string) {
  14. return s.length === 5 && numberRegexp.test(s);
  15. }
  16. }
  17. }
  18. // Some samples to try
  19. var strings = ['Hello', '98052', '101'];
  20. // Validators to use
  21. var validators: { [s: string]: Validation.StringValidator; } = {};
  22. validators['ZIP code'] = new Validation.ZipCodeValidator();
  23. validators['Letters only'] = new Validation.LettersOnlyValidator();
  24. // Show whether each string passed each validator
  25. strings.forEach(s => {
  26. for (var name in validators) {
  27. console.log('"' + s + '" ' + (validators[name].isAcceptable(s) ? ' matches ' : ' does not match ') + name);
  28. }
  29. });

分离模块文件

随着程序的增长,我们需要把代码分割到很多文件中来让其更加易于维护。

现在,我们把Validation module 分割到多个文件中。虽然他们被分割了,但是它们依然包含在同一个module中,并且在使用中和声明在一个位置是一样的。因为文件之间的依赖关系,所以我们在文件开头添加了引用的标签来告诉编译器他们之间的引用关系,除此我们测试代码是没有变化的。

多文件的内部modules

Validation.ts

  1. module Validation {
  2. export interface StringValidator {
  3. isAcceptable(s: string): boolean;
  4. }
  5. }

LettersOnlyValidator.ts

  1. /// <reference path="Validation.ts" />
  2. module Validation {
  3. var lettersRegexp = /^[A-Za-z]+$/;
  4. export class LettersOnlyValidator implements StringValidator {
  5. isAcceptable(s: string) {
  6. return lettersRegexp.test(s);
  7. }
  8. }
  9. }

ZipCodeValidator.ts

  1. /// <reference path="Validation.ts" />
  2. module Validation {
  3. var numberRegexp = /^[0-9]+$/;
  4. export class ZipCodeValidator implements StringValidator {
  5. isAcceptable(s: string) {
  6. return s.length === 5 && numberRegexp.test(s);
  7. }
  8. }
  9. }

Test.ts

  1. /// <reference path="Validation.ts" />
  2. /// <reference path="LettersOnlyValidator.ts" />
  3. /// <reference path="ZipCodeValidator.ts" />
  4. // Some samples to try
  5. var strings = ['Hello', '98052', '101'];
  6. // Validators to use
  7. var validators: { [s: string]: Validation.StringValidator; } = {};
  8. validators['ZIP code'] = new Validation.ZipCodeValidator();
  9. validators['Letters only'] = new Validation.LettersOnlyValidator();
  10. // Show whether each string passed each validator
  11. strings.forEach(s => {
  12. for (var name in validators) {
  13. console.log('"' + s + '" ' + (validators[name].isAcceptable(s) ? ' matches ' : ' does not match ') + name);
  14. }
  15. });

如果涉及多个文件,我们需要确保所有需要编译的代码能够正确的加载。有两种方法能够使用。
第一种:我们可以使用--out 命令串联所有输入的文件编译到一个javascript文件:

  1. tsc --out sample.js Test.ts

编译器会自动根据引用标签编译到一个js文件。你也可以详细指定文件:

  1. tsc --out sample.js Validation.ts LettersOnlyValidator.ts ZipCodeValidator.ts Test.ts

第二种:我们也可以采用预先文件的编辑来加载多个文件,我们可以使用script tag在web页面加载来控制文件顺序,例如:
MyTestPage.html (excerpt)

  1. <script src="Validation.js" type="text/javascript" />
  2. <script src="LettersOnlyValidator.js" type="text/javascript" />
  3. <script src="ZipCodeValidator.js" type="text/javascript" />
  4. <script src="Test.js" type="text/javascript" />

Going External

Export =

Alias

Optional Module Loading and Other Advanced Loading Scenarios

Working with Other JavaScript Libraries

Pitfalls of Modules

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注