转自:http://www.hubwiz.com/


模块的声明


  前端数据验证在改善用户体验上有很大作用,在学了前面的知识,我们很可能会写出以下代码:


interface StringValidator {  //定义验证接口

 isAcceptable(s: string): boolean;

}

 

var lettersRegexp = /^[A-Za-z]+$/;

var numberRegexp = /^[0-9]+$/;

 

class LettersOnlyValidator implements StringValidator { //实现接口

 isAcceptable(s: string) {

   return lettersRegexp.test(s);

 }

}

 

class ZipCodeValidator implements StringValidator {   //实现接口

 isAcceptable(s: string) {

   return s.length === 5 && numberRegexp.test(s);

 }

}

 

var strings = ['Hello', '98052', '101'];

var validators: { [s: string]: StringValidator; } = {};

validators['ZIP code'] = new ZipCodeValidator();  //实例化类

validators['Letters only'] = new LettersOnlyValidator(); //实例化类

for(var i=0;i<strings.length;i++){

   for (var name in validators) {

      document.write('"' + strings[i] + '" ' + (validators[name].isAcceptable(strings[i]) ? ' matches ' : ' does not match ') + name+"<br>"); //调用类的方法

   }

}


  那么这段代码最大的问题是什么呢?一个是没法复用,验证的封装和验证过程在同一个文件,验证的封装已经是可以复用的。另一个是接口和两个实现的类都直接挂接在全局变量上,假如数量一多的话,将会影响整个全局变量。

  而TypeScript中模块的出现给我们解决了这一问题。使用 module 关键字来定义模块,并在末尾加花括号即可用; 用export 关键字使接口、类等成员对模块外可见。


module Validation {   //定义模块

 export interface StringValidator {  //声明接口对外部可以使用

   isAcceptable(s: string): boolean;

 }

 

 var lettersRegexp = /^[A-Za-z]+$/;

 var numberRegexp = /^[0-9]+$/;

 

 export class LettersOnlyValidator implements StringValidator {  //声明类对外部可用

   isAcceptable(s: string) {

     return lettersRegexp.test(s);

   }

 }

 

 export class ZipCodeValidator implements StringValidator {

   isAcceptable(s: string) {

     return s.length === 5 && numberRegexp.test(s);

   }

 }

}


模块内容的调用


  在前面一节中我学习了模块的声明,而在模块声明完成以后,我们就可以调用这个模块了,调用模块中的接口、类、方法等。调用方法简单,就是用模块名后面跟一个点来调用类、接口、方法等。如下代码:


module Validation {  //定义模块

 export interface StringValidator {  //声明接口对外部可以使用

     isAcceptable(s: string): boolean;

 }

 

 var lettersRegexp = /^[A-Za-z]+$/;

 var numberRegexp = /^[0-9]+$/;

 

 export class LettersOnlyValidator implements StringValidator { //声明类对外部可用

   isAcceptable(s: string) {

     return lettersRegexp.test(s);

   }

 }

 

 export class ZipCodeValidator implements StringValidator {

   isAcceptable(s: string) {

     return s.length === 5 && numberRegexp.test(s);

   }

 }

}

 

var strings = ['Hello', '98052', '101'];

var validators: { [s: string]: Validation.StringValidator; } = {};

validators['ZIP code'] = new Validation.ZipCodeValidator();  //使用模块中的类

validators['Letters only'] = new Validation.LettersOnlyValidator();

// 显示匹配结果

for(var i=0;i<strings.length;i++){

 for (var name in validators) {

    document.write('"' + strings[i] + '" ' + (validators[name].isAcceptable(strings[i]) ? ' matches ' : ' does not match ') + name+"<br>"); // 使用方法

   }

}


分隔模块到多个文件


  随着我们项目的扩展,我们的代码总不可能只写在一个文件里。为了更好地维护项目,我们会将特定功能放到一个文件里,然后加载多个文件实现我们想需要的功能。现在我们先将上面的代码分割到多个文件里。

Validation.ts


module Validation {

 export interface StringValidator {

     isAcceptable(s: string): boolean;

 }

}


LettersOnlyValidator.ts


/// <reference path="Validation.ts" />

module Validation {

 var lettersRegexp = /^[A-Za-z]+$/;

 export class LettersOnlyValidator implements StringValidator {

     isAcceptable(s: string) {

       return lettersRegexp.test(s);

     }

 }

}


ZipCodeValidator.ts



/// <reference path="Validation.ts" />

module Validation {

 var numberRegexp = /^[0-9]+$/;

 export class ZipCodeValidator implements StringValidator {

   isAcceptable(s: string) {

     return s.length === 5 && numberRegexp.test(s);

   }

 }

}


Test.ts


/// <reference path="Validation.ts" />

/// <reference path="LettersOnlyValidator.ts" />

/// <reference path="ZipCodeValidator.ts" />

 

var strings = ['Hello', '98052', '101'];

var validators: { [s: string]: Validation.StringValidator; } = {};

validators['ZIP code'] = new Validation.ZipCodeValidator();

validators['Letters only'] = new Validation.LettersOnlyValidator();

for(var i=0;i<strings.length;i++){

 for (var name in validators) {

    document.write('"' + strings[i] + '" ' + (validators[name].isAcceptable(strings[i]) ? ' matches ' : ' does not match ') + name+"<br>"); //调用类的方法

   }

}


  在项目中新建好以上四个文件,然后我们编译项目,如果我们代码编写没错的话,是能够编译通过的。另外,我们可以见到后面三个文件开头有类似于 C# 的文档注释,这是告诉 TypeScript 编译器该文件依赖于哪些文件,假如依赖的文件不存在的话,编译就会不通过。当然我们不写也是可以的,只不过编译器在编译时不会帮我们检查,一般来说,还是建议写上。 另外,在引用编译生成的 JavaScript 文件时,我们需要注意好顺序。以上面的代码为例,我们在 Html 代码中已经这么引用。


<script src="Validation.js" type="text/javascript"/>

<script src="LettersOnlyValidator.js" type="text/javascript"/>

<script src="ZipCodeValidator.js" type="text/javascript"/>

<script src="Test.js" type="text/javascript"/>