Typescript模块化/命名空间/装饰器

模块的概念(官方)

  关于术语的一点说明:请务必注意一点,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()

  

原文地址:https://www.cnblogs.com/double-W/p/12879263.html