七、装饰器

装饰器

装饰器是一种特殊类型的声明,它能够被附件到类声明,方法,属性或参数上,可以修改其行为扩展其功能。

分类:类装饰器、属性装饰器、方法装饰器、参数装饰器

写法包含:普通装饰器(无法传参)、装饰器工厂(可传参)

要启用对decorator的实验支持,您必须在命令行或tsconfig.json中启用experimental aldecorators编译器选项

tsc --target ES5 --experimentalDecorators
---------------------------tsconfig.ts--------------
{
    "compilerOptions": {
        "target": "ES5",
        "experimentalDecorators": true
    }
}
类装饰器

类装饰器在类声明之前被声明(紧靠着类声明),类装饰器应用于类构造函数,可以用来监视、修改或替换类定义。在不修改类前提下可以扩展类属性

//普通类装饰器 执行顺序order1->order2
function logClass(params:any){
	console.log("order1")
    console.log(params);// params 为class Httpclient
    params.prototype.name='12动态扩展属性'// 使用es5的方式扩展属性和方法
} 
@logClass
class Httpclient{
    constructor(){
    console.log("order2")
    }
    getDate(){
    }
}
let h:any = new Httpclient();
console.log(h.name);
//===================================
执行顺序为order1->order2->order3 
// 装饰器修改类构造函数,类装饰器重载构造函数
function logClass(target:any){// 此处为装饰器传入的参数
     console.log("order1")
    return class extends target{// 重载方法及其属性,'class extends',此处重写了class Httpclient
        apiurl:string
        constructor(){
            super()
            console.log("order3")
            this.apiurl = '123';    
        }
        getDate(){  }
    }
}
@logClass
class Httpclient{
    apiurl!:string;
    constructor(){
        console.log("order2")
        this.apiurl='2.apiurl'
    }
    getDate(){   }
}
let h = new Httpclient();
console.log(h.apiurl)
//===================================
// 装饰器工厂 执行顺序order1->order2->order3
function logClass(param:string){// 此处为装饰器传入的参数
     console.log("order1")
    return function(target:any){ // 工厂装饰器返回为一个函数,函数参数为class Httpclient
        target.prototype.apiurl = '1.apiurl'
        console.log("order2")
    }
}
@logClass("param1")
class Httpclient{
    apiurl!:string;
    constructor(){
        // this.apiurl='2.apiurl'
        console.log("order3")
    }
    getDate(){
    }
}
let h = new Httpclient();
console.log(h.apiurl)
//======
// 类装饰器
function logClass(param:any){// 此处为装饰器传入的参数
    console.log("order1")
    // return class extends param{ // 写法对应为 @logClass
    //     apiurl!:string;
    //     getDate(){}
    // }

    // return function(target:any){ // 写法对应为@logClass('param') ,工厂装饰器返回为一个函数,函数参数为class Httpclient ,
    //     target.prototype.apiurl = '1.apiurl'
    //     console.log("order2")
    // }
}
属性装饰器

属性装饰器的执行顺序早于在类装饰器

属性装饰器表达式会在运行时当作函数被调用,传入下列2个参数

  • 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
  • 成员的名字
// 属性装饰器
function logProperties(param?:any,param2?:string){// 该函数参数个数及类型根据功能需求而定
    console.log("order4|")
    return function(target:any,attr:any){
        console.log("order5+")
        target[attr]=''
    }
}

class Httpclient{
    
    @logProperties('dd') // 当作函数被调用
    apiurl:string;

    constructor(){
        this.apiurl='2.apiurl'
        console.log("order3")
    }
    getDate(){

    }
}
let h = new Httpclient();
方法装饰器

它被应用到方法的属性描述上,可以用来监视,修改或者替换方法定义。

方法装饰器会在运行时传入下列三个参数:

  • 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
  • 方法的名称
  • 方法的属性描述
// 方法装饰器
function get(param:any){
    return function(target:any,methodName:any,desc:any){
    /*三个参数为
    1-----
    Httpclient { getDate: [Function], apiurl: '' },
    getDate,
    { value: [Function],
      writable: true,
      enumerable: true,
      configurable: true }
    2-----
    */
        target.apiurlww2 = '1.apiurlww2'// 扩展原型类属性 不使用es5 prototype方式
        target.run= function(param1:string):any{// 扩展原型类方法
            return "run+"+param1;
        }
        desc.value= function(age:number):any{// 替换重写装饰器方法
            return 'getDate Method decorated'+age;
        }
        // 修改装饰器
        var oriMethod = desc.value;
        desc.value= function():any{// 修改装饰器方法
            var mes=  'getDate Method decorated';
            console.log(mes);
            oriMethod.apply(this,console.log(mes)) // apply方法使用作为修改装饰器
            return mes
        }
    }
}
class Httpclient{
    
    @get('ww')
    getDate(){

    }
}
console.log(h.apiurlww2)
console.log(h.run('ww'))

apply:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.apply(A, arguments);即A对象应用B对象的方法。

call:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.call(A, args1,args2);即A对象调用B对象的方法。

// 方法装饰器
function get(target:any,methodName:any,desc:any){
        
        var oriMethod = desc.value;
        desc.value= function():any{// 替换装饰器方法
            var mes=  'getDate Method decorated';
            console.log(mes);
            oriMethod.apply(this,console.log(mes))
            // return mes
        }        
    }
    
 使用为@get
 class Httpclient{
    
    @get
    getDate(){

    }
}
方法参数装饰器

参数装饰器表达式会在运行时单过函数被调用,可以使用参数装饰器为类的原型增加一些元数据,传入下列3个参数:

  • 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
  • 参数的名称
  • 参数在函数参数列表中的索引
import "reflect-metadata";

const requiredMetadataKey = Symbol("required");

function required(target: Object, propertyKey: string | symbol, parameterIndex: number) {
    let existingRequiredParameters: number[] = Reflect.getOwnMetadata(requiredMetadataKey, target, propertyKey) || [];
    existingRequiredParameters.push(parameterIndex);
    Reflect.defineMetadata(requiredMetadataKey, existingRequiredParameters, target, propertyKey);
}


class Greeter {
    greeting: string;

    constructor(message: string) {
        this.greeting = message;
    }

    greet(@required name: string) {
        return "Hello " + name + ", " + this.greeting;
    }
}
装饰器执行顺序
属性装饰器【多个则从下到上执行】  -> 方法装饰器【多个则从下到上执行】 -> 方法参数装饰器【多个则从右到左执行】 -> 类装饰器【多个则从下到上执行】

参数装饰器

方法装饰器

@required @validate

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可私 6信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 、可私信6博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 、可私信6博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值