模块的概念(官方)
关于术语的一点说明:请务必注意一点,Typescript里面发生变化,“内部模块”现在成为“命名空间”。“外部模块”现在简称为“模块”,模块在其自身的作用域里执行,而不是在全局作用域里;这意味着定义在一个模块里的变量,函数,类等在模块外部是不可见的,除非你明确使用export形式导出,相反,如果想使用其他模块的变量,函数,类等,你必须要导入它们,可以使用import形式
模块的理解:
我们可以把一些公用的功能单独抽离成一个文件作为模块,模块里面的变量、函数、类等默认是私有的,如果我们要在外部访问模块里面的数据,我们需要通过export暴露里面的数据(变量、函数、类等),暴露后我们通过import引入模块可以使用模块里面的数据。
- 项目同级创建一个modules文件,写一个db.ts
var dbUrl = 'xxx' export function getData(){ console.log("获取数据库数据") return [ { title:'1' }, { title:'2' } ] } export {dbUrl}
- 修改index.ts文件
import {getData,dbUrl as Url} from './modules/db' getData(); console.log(Url)
命名空间
为了防止变量名等命名重复问题,这里使用命名空间区分。
namespace A{ // 创建一个命名空间 interface Animal { name:string; eat():void; } export class Dog implements Animal { // 这里也需要导出一个类 name:string; constructor(name:string){ this.name = name; } eat(){ console.log(this.name+"吃饭"); } } } var d = new A.Dog("小黑"); d.eat() // 当出现几个开发的时候,命名重复,这里则通过命名空间区分
如果想把命名空间做成模块化,需要如下使用
// modules文件的name.ts文件 export namespace A{ // 创建一个命名空间 interface Animal { name:string; eat():void; } export class Dog implements Animal { // 这里也需要导出一个类 name:string; constructor(name:string){ this.name = name; } eat(){ console.log(this.name+"吃饭"); } } } // 使用是的index.ts import {A} from './modules/name' var a = A.Dog("xxx") a.eat()
装饰器
装饰器是一种特殊类型的声明,它能够被附加到类声明、方法、属性或参数上,可以修改类的行为,通俗来将装饰器就是一个方法注入到类、方法、属性参数上的扩展功能,常见的装饰器:类装饰器、属性装饰器、方法装饰器、参数装饰器;
常见的写法:普通装饰器(无法传参)、装饰器工厂(可传参数)
类装饰器:声明之前,用于类构造函数,可以监视、修改或替换类定义
//方法1:普通类装饰器 function logClass(params:any) { // 需要写一个参数接受类名 console.log(params) // params就是当前类 // 扩展类属性 params.prototype.apiUrl = 'xxxx' // 扩展方法 params.prototype.run= function(){ console.log("running...") } } @logClass class HttpClient { constructor() { } getData() { } } var http:any = new HttpClient(); console.log(http.apiUrl) http.run(); //方法2: 装饰器工厂(可传参) function logClass1(params:string){ return function(target:any) { console.log(target) console.log(params) // hello target.prototype.apiUrl = 'www' } } @logClass1('hello') // 需要传入参数 class HttpClient1 { constructor() { } getData() { } } var h:any = new HttpClient1(); console.log(h.apiUrl) // 类装饰器: 会在运行是当作函数调用,类的构造函数作为其唯一的参数,如果类装饰器返回一个值,它会 // 使用提供的构造函数替换类的声明 function logClass2 (target:any){ console.log(target); return class extends target{ // 重载类装饰器 apiUrl:any = "我是重载后的url" // 这样就会重载之前的属性 getData(){ this.apiUrl = this.apiUrl+'xxx' console.log(this.apiUrl) } } } @logClass2 class HttpClient2 { public apiUrl:string|undefined; constructor() { this.apiUrl = '我是构造函数里面的apiUrl' } getData() { console.log(this.apiUrl) } } var h1 = new HttpClient2(); h1.getData(); // 类装饰器 function logClass3(params:string){ return function(target:any) { console.log(target) console.log(params) // hello target.prototype.apiUrl = 'www' } } // 属性装饰器 function logProperty(params:any){ return function(target:any,attr:any){ console.log(target) // 类原型对象 console.log(attr) // 类属性 target[attr] = params } } @logClass3('xxxx') // 需要传入参数 class HttpClient3 { @logProperty("http:www.baidu.com") public url:any |undefined constructor() { } getData() { console.log(this.url) } } var h2 = new HttpClient3() h2.getData()