【TypeScript】TS进阶-装饰器(九)

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

🐱个人主页不叫猫先生
🙋‍♂️作者简介前端领域新星创作者、阿里云专家博主专注于前端各领域技术共同学习共同进步一起加油呀
💫系列专栏vue3从入门到精通TypeScript从入门到实践
📢资料领取前端进阶资料以及文中源码可以找我免费领取
🔥社群招募博主建立了一个前端交流群汇集了各路大神期待你的加入(文末有我wx或者私我)

目录

专栏介绍

TypeScript从入门到实践专栏是博主在学习和工作过程中的总结实用性非常强内容会不断进行精进欢迎订阅哦学会TS不迷路。

TS系列标题
基础篇TS入门一
基础篇TS类型声明二
基础篇TS接口类型三
基础篇TS交叉类型&联合类型四
基础篇TS类型断言五
基础篇TS类型守卫六
进阶篇TS函数重载七
进阶篇TS泛型八
进阶篇TS装饰器九

装饰器

**装饰器Decorator**是一种特殊类型的声明它能够被附加到类声明、方法、属性或参数上装饰器的本身。其本身是一个函数会在运行的时候被调用被装饰的声明信息会作为参数传递给装饰器函数当作形参。装饰器本质上主要是在操作原型对象通过给原型对象 prototype添加一些方法和属性来扩展类的功能。
装饰器主要分为类装饰器接收1个参数、属性装饰器接收2个参数、方法装饰器接收3个参数、参数装饰器接收3个参数不同装饰器接收参数也不一同。另外TS内置了装饰器类型我们直接用就好了。

装饰器分类ts内置装饰器类型接收参数
类装饰器ClassDecorator1个类函数
方法装饰器MethodDecorator3个类函数方法名成员属性描述符
属性装饰器PropertyDecorator2个类函数、属性名称
参数装饰器ParameterDecorator3个类函数参数名参数所在位置的索引

要想在 TypeScript 中使用装饰器必须将 tsconfig.jsonexperimentalDecorators设置为true具体如下所示

  • 生成tsconfig.json文件
tsc --init
  • 配置
tsc --target ES5 --experimentalDecorators
{
  "compilerOptions": {
    "target": "ES5",
    "experimentalDecorators": true,                   /* Enable experimental support for TC39 stage 2 draft decorators. */
    "emitDecoratorMetadata": true,                    /* Emit design-type metadata for decorated declarations in source files. */
    }
 }
  • 语法
    @expressionexpression是一个函数位置根据不同类型的装饰器要求放置。

1、类装饰器

1一个装饰器

类装饰器接收一个构造函数作为参数参数的类型是一个函数。

function ClassDecorator(target: Function): void {
  target.prototype.start = function(): void {
      // 通用功能
      console.log('1')
  }
}
@ClassDecorator
class Course {
  constructor() {
      // 业务逻辑
  }
}
let course = new Course();
console.log('course',course.start())

2装饰器累加

装饰器不是只能定义一个可以定义多个作用于一个类函数通过装饰器累加从而给类追加多个方法和属性可以用来监视、修改、替换类定义。

  • 参数只有target一个意思是类函数本身
function StartTime(target: Function): void {
  target.prototype.start = function(): void {
      // 通用功能
      console.log('start')
  }
}
function EtartTime(target: Function): void {
  target.prototype.end = function(): void {
      // 通用功能
      console.log('end')
  }
}
@StartTime
@EndTime
class Course {
  constructor() {
      // 业务逻辑
  }
}
let course = new Course();
console.log('course',course.start())
console.log('course',course.end())

3装饰器传参

装饰器传参那么怎么接受呢参数如何放置只需要在内部再返回一个装饰器就可参数在外部进行接收具体例子如下所示

function ClassDecorator(name: string) {
  return (target: any)  => {
    target.prototype.name = name
  }
}
@ClassDecorator('zhangsan')
class Course {
  constructor() {
      // 业务逻辑
  }
}
let course:p = new Course();
interface p {
   name?:string
}
console.log('course',course.name)//zhangsan

2、方法装饰器

方法装饰器使用与类装饰器基本相同方法装饰器需要放在类方法的前面方法作为参数传给方法装饰器接收三个参数具体如下

  • target: 对于静态成员来说是类的构造函数对于实例成员是类的原型对象。
  • propertyKey: 方法名称。
  • descriptor: 成员的属性描述符。

//PropertyDescriptor类型是ts内置的
function MethodsDecorator (target: Object, propertyKey: string, descriptor: PropertyDescriptor){
     console.log(target)
     console.log(propertyKey)
     console.log(descriptor)
}

class Person {
    name: string = ''
    age: number = 0

    constructor(name: string, age: number) {
        this.name = name
        this.age = age
    }

    @MethodsDecorator
    getName() {
      return this.name
    }

    @MethodsDecorator
    getAge() {
      return this.age
    }
}

const p = new Person('张三', 18)
p.getName() // getName张三
p.getAge() // getAge18

在这里插入图片描述
我们可以看到打印出来的值getNamegetAge被一一打印出来以及属性描述符。其中属性描述符主要包括以下四个属性

  • configurable是否可删除
  • enumerable是否可枚举
  • value属性值
  • writable是否可修改

3、属性装饰器

属性装饰器只接收两个参数具体如下

  • target: 对于静态成员来说是类的构造函数对于实例成员是类的原型对象。
  • propertyKey属性名称
const propertyName = (target: Object, propertyKey: string) => {
  console.log(target, propertyKey)
}

class Person {
    @propertyName 
    name: string = ''
    @propertyName
    age: number = 0

    constructor(name: string, age: number) {
        this.name = name
        this.age = age
    }
}
const p = new Person('张三', 18)

打印结果如下所示

在这里插入图片描述

注意如果@propertyName 只写在name: string = ''上面则只会打印出name相关的数据。

4、参数装饰器

参数装饰器用于装饰函数的参数与方法装饰器一样接收三个参数具体如下

  • target对于静态成员来说是类的构造函数对于实例成员是类的原型对象。
  • propertyKey属性名称。
  • paramIndex:参数所在位置的索引
const paramDecorator = (target: any, propertyKey: string, paramIndex: number) => {
    console.log(target, propertyKey, paramIndex)
}

class Person {
    name: string = '';
    age: number = 0;
    
    constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
    }

    setName(age:number,@paramDecorator name: string) {
      this.name = name;
      this.age = age;
    }
}

const p = new Person('张三', 18) 
p.setName(1,'李四')

打印结果如下所示
在这里插入图片描述

5、实际应用

1错误信息自定义

怎么使用装饰器进行错误信息自定义这里使用方法装饰器来对传进来的函数进行处理主要步骤如下

  • 解构参数
  • 取到传进来的函数
  • 使用try...catch执行函数新的报错定义在catch
  const ErrorDecorator:MethodDecorator = (...args: any[]) => {

    const [,,descriptor] = args;
    const method = descriptor.value
    descriptor.value = () =>{
      try {
        method()
      } catch (error) {
        console.log('这是新定义的错误')
      }    
    }
  }

  class User {
    @ErrorDecorator
    public errorMsg () {
      throw new Error('报错了')
    }

  }
  new User().errorMsg()

在使用装饰器时先将原有的值进行存储一下再去使用以此来确保它使用的是类中的方法中的值。

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6