美文网首页
typeScript--再学装饰器

typeScript--再学装饰器

作者: 习惯水文的前端苏 | 来源:发表于2023-04-03 20:27 被阅读0次

好文推荐

localStorage的别样用法
借助npm包统一包管理器

前言

约是两年前,就对着ts文档学习了装饰器的使用,我是相信温故而知新的,故今天重新在学一遍,相信会有不一样的收获

启用

在项目中,需要在tsconfig.json中显示的启用

{
  "compilerOptions": {
    "experimentalDecorators": true
  }
}

装饰器分类

1-类装饰器
2-属性装饰器
3-方法装饰器
4-参数装饰器
5-访问器装饰器

执行顺序

  • 参数装饰器,然后依次是方法装饰器,访问符装饰器,或属性装饰器应用到每个实例成员
  • 参数装饰器,然后依次是方法装饰器,访问符装饰器,或属性装饰器应用到每个静态成员
  • 参数装饰器应用到构造函数。
  • 类装饰器应用到类。

使用

  • 类装饰器

1-其ts定义如下

可以看到,类的本质是Function类型,这意味着,我们可以通过prototype来进行扩展,同时从返回值可以猜测,如果返回值类型不是void,则极大可能性会将返回的值作为装饰器本身

declare type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;

2-返回void

function sex<T extends {new(...args:any[]):{}}>(constructor:T){
  constructor.prototype.logSex = function(){
    console.log('男')
  }
}

@sex
class Person{
}

(new Person() as any).logSex()

3-返回Function

上一个返回void的示例是无法传递参数的,可以通过返回函数类型来解决

function sex(msg:string){
  return function<T extends {new(...args:any[]):{}}>(constructor:T){
    constructor.prototype.logSex = function(){
      console.log(msg)
    }
  }
}

@sex('用户的')
class Person{
}
(new Person() as any).logSex()

4-重载

由于class本质上也是Function类型,所以这可以看作是3的另一种表达形式,且更灵活些

function sex<T extends {new(...args:any[]):{}}>(Tar:T){
  return class extends Tar{
    constructor(...args:any[]){
      super()
    }
  }
}

@sex
class Person{
}
  • 属性装饰器

1-定义

从定义可知,其也是一个函数,且被执行时会接收两个参数

1-对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
2-成员的名字

declare type PropertyDecorator = (target: Object, propertyKey: string | symbol) => void;

2-使用

我们可以对某个属性进行监控,并当某个操作行为发生时执行一些关联动作

function reactive(Tar:any,p:string){
  let value = Tar[p]

  const get = function(){
    return value
  }

  const set = function(newValue:any){
    Tar.changeName(newValue)
    value = newValue
  }

  if(Reflect.deleteProperty(Tar,p)){
    Object.defineProperty(Tar,p,{
      set,
      get,
      enumerable:true,
      configurable:true
    })
  }

}

class Person{
  @reactive
  name:string=''
  changeName(newName:string){
    console.log('改名字了,新名字是:'+newName)
  }
}
const p = new Person() 
p.name
p.name = '23'
console.log(p.name)
  • 方法装饰器

1-定义

declare type MethodDecorator = 
<T>(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) 
=> TypedPropertyDescriptor<T> | void;

相比较属性选择器,其多了参数三,其对应的ts定义如下

value属性表示的是函数体,这意味着可以先将原函数体缓存后执行重写等操作

interface TypedPropertyDescriptor<T> {
    enumerable?: boolean;
    configurable?: boolean;
    writable?: boolean;
    value?: T;
    get?: () => T;
    set?: (value: T) => void;
}

2-示例

拿我之前写npm包时遇到的一个需求举例,在初始化的时候用到了异步数据,在异步执行结束前如果用户执行了do方法,则需要对其进行缓存,等异步结束后再取回依次调用,伪代码如下

import { config } from '.'

function delay(_,_, descriptor){
  const value = descriptor.value
  descriptor.value = function(...args:any[]){
    if(config.asyning){
        config.que.push(descriptor)
    }else{
      value.apply(this,args)
      config.que = []
    }
  }
  return descriptor
}

class NAS{
  @delay
  do(){
  }
}
  • 参数装饰器

1-定义

declare type ParameterDecorator = 
(target: Object, propertyKey: string | symbol, parameterIndex: number) => void;

2-示例

在参数装饰器执行时收集必选信息,当运行方法装饰器时重写descriptor.value并加入判断逻辑

const requiredMap:any = {

}
function required(_: any, propertyKey: string, parameterIndex: number){
  requiredMap[propertyKey]=parameterIndex
}

function validate(_:any,__:any, descriptor:any){
  const i = requiredMap[descriptor.value.name]
  if(i !== undefined){
    descriptor.value = (...args:any[])=>{
      if(args[i] === undefined){
        throw new Error('参数缺失')
      }
    }
  }
  return descriptor
}

class Person{
  @validate
  changeName(@required newName:string){
    console.log('改名字了,新名字是:'+newName)
  }
}
const p = new Person() 
p.changeName()
  • 访问器装饰器

看文档吧,感觉没啥可说的,主要没实际用过,后续有应用场景了补充

相关文章

  • 装饰器

    """@装饰器- 普通装饰器- 带参数的装饰器- 通用装饰器- 装饰器装饰类- 内置装饰器- 缓存装饰器- 类实现...

  • typescript 五种装饰器

    装饰器类型 装饰器的类型有:类装饰器、访问器装饰器、属性装饰器、方法装饰器、参数装饰器,但是没有函数装饰器(fun...

  • python——装饰器详解

    一、装饰器概念 1、装饰器 装饰器:一种返回值也是一个函数的函数,即装饰器。 2、装饰器目的 装饰器的目的:装饰器...

  • Python装饰器

    Python装饰器 一、函数装饰器 1.无参装饰器 示例:日志记录装饰器 2.带参装饰器 示例: 二、类装饰器 示例:

  • Python中的装饰器

    Python中的装饰器 不带参数的装饰器 带参数的装饰器 类装饰器 functools.wraps 使用装饰器极大...

  • 装饰器

    装饰器 decorator类装饰器 带参数的装饰器 举例(装饰器函数;装饰器类;有参与无参) https://fo...

  • TypeScript装饰器

    前言 装饰器分类 类装饰器 属性装饰器 方法装饰器 参数装饰器需要在tsconfig.json中启用experim...

  • python之装饰器模版

    装饰器的作用:装饰器即可以装饰函数也可以装饰类。装饰器的原理:函数也是对象 1.定义装饰器 2.使用装饰器假设de...

  • 装饰器实验

    装饰器实验 说明 ts内包含了四个装饰器,类装饰器、属性装饰器、函数装饰器、参数装饰器,本文中测试一下其的使用。 ...

  • python3基础---详解装饰器

    1、装饰器原理 2、装饰器语法 3、装饰器执行的时间 装饰器在Python解释器执行的时候,就会进行自动装饰,并不...

网友评论

      本文标题:typeScript--再学装饰器

      本文链接:https://www.haomeiwen.com/subject/vlmdddtx.html