ts 装饰器

news2024/11/15 15:45:21
  • 使用装饰器前,需要把 tsconfig.json 中 experimentalDecorators 设置为 true
  • 学习了小满的B站课程:https://www.bilibili.com/video/BV1wR4y1377K?p=24

前言

ts中有几种装饰器类型:

  • 类装饰器 ClassDecorator
  • 方法装饰器 MethodDecorator
  • 参数装饰器 ParameterDecorator
  • 属性装饰器 PropertyDecorator

一、类装饰器 ClassDecorator

  • 功能 & 使用场景:不想破坏原有的类的结构,又不想去读内部的代码逻辑,只想 给类增加一些新的属性或方法,可对该类使用装饰器
  • 装饰器需要定义为 ClassDecorator 类型
  • 装饰器回传参数 target, 是调用者的 构造函数
  • 两种使用方式:
    • 在 class 前 @DecoratorName
    • 在 class 后 DecoratorName(className)

1、类装饰器的简单使用

const DecoratorClassDemo: ClassDecorator = (target) => {
  // 回传的 target 是调用者的构造函数
  // 可以额外定义属性、方法
  target.prototype.color = 'blue'
  target.prototype.showColor = () => {
    console.log('哈哈哈哈')
  }
}

// 写法一:若担心浏览器不支持,可以使用写法二
@DecoratorClassDemo
class Http {
  // 不想读里面的逻辑,又想加一些东西,并且不破坏原有的结构,可以考虑在外层使用装饰器
}
// 写法二:
// DecoratorClassDemo(Http)

// 将类实例化后,可以访问到装饰器里新增的属性和方法
const http = new Http() as any
console.log('http.color', http.color) // blue
http.showColor()

如果想要 传参数 给类装饰器,怎么做?

2、装饰器工厂

可以先把它定义为 普通函数(保证参数的接收),然后在其 内部返回一个装饰器函数 即可(闭包)

// 可以先把它定义为普通函数(保证参数的接收),然后在其内部返回一个装饰器函数即可
const DecoratorClassDemo2 = (msg: string, age: number) => {
  const fn: ClassDecorator = (target) => {
    target.prototype.msg = msg
    target.prototype.age = age
  }
  return fn
}
@DecoratorClassDemo2('hahaha', 18)
class Http2 {
  // .....
}
const http2 = new Http2() as any
console.log('类装饰器传参---', http2.msg)
console.log('类装饰器传参---', http2.age)

同样的方式在其他装饰器中也有使用

二、方法装饰器 MethodDecorator

  • 顾名思义,就是对 方法 使用装饰器,在方法前 @DecoratorName
  • 方法装饰器需要声明为 MethodDecorator 类型
  • 方法装饰器回传参数:target, propertyKey, descriptor
    • target:调用者的 原型
    • propertyKey: 调用者的 key,即 方法名称
    • descriptor:调用者的 描述
  • 方法装饰器 想要 回调数据给调用者,需要 把 descriptor 声明为 PropertyDescriptor 类型,通过 descriptor.value 返回

例:写一个简单的Get请求装饰器

// 安装:npm i axios 
import axios from 'axios'

const Get = (url: string) => {
  // 这里注意把 descriptor 定义为 PropertyDescriptor 类型
  const fn: MethodDecorator = (target, propertyKey, descriptor: PropertyDescriptor) => {
    // 【target】:{constructor: ƒ, getList: ƒ}
    // 【propertyKey】:getList
    // 【descriptor】:{writable: true, enumerable: false, configurable: true, value: ƒ}

    axios.get(url).then(res => {
      // 拿到结果后通过 descriptor 的 value 返回(注意value是个函数)
      descriptor.value(res.data) 
    })
  }
  return fn
}

class Http3 {
  // 对 getList  使用 方法装饰器 Get
  @Get('https://api.apiopen.top/api/getHaoKanVideo?page=1&size=10')
  getList (data: any) {
    console.log(data)
  }
}

最终打印出的 data:

在这里插入图片描述

三、参数装饰器 ParameterDecorator

  • 顾名思义,对 参数 使用装饰器,在参数前 @DecoratorName
  • 参数装饰器需要定义为 ParameterDecorator 类型
  • 参数装饰器回传参数: target, propertyKey, parameterIndex
    • target:调用者的 原型
    • propertyKey:调用者的 方法名称
    • parameterIndex:该参数是方法中的 第几个参数
  • 需要用到插件 reflect-metadata使用元数据
    • 安装命令: npm i reflect-metadata
    • tsconfig.json 中需要将 emitDecoratorMetadata 开启
    • Reflect.defineMetadata存入元数据,参数如下:
      • metadataKey: 所要存元数据的 key
      • metadataValue: 对应的 value
      • target: 存入的 目标
    • Reflect.getMetadata取出元数据,参数如下:
      • metadataKey:所要取的元数据的 key
      • target:所要取的 目标

在上面的基础上继续造例子,将 参数data 处理为优先返回内部的 result

import axios from 'axios'
import 'reflect-metadata'

const Result = () => {
  const fn: ParameterDecorator = (target, propertyKey, parameterIndex) => {
    // 【target】:{constructor: ƒ, getList: ƒ} 
    // 【propertyKey】:getList 
    // 【parameterIndex】:0
    
    // 存入数据:key='result'
    Reflect.defineMetadata('key', 'result', target)
  }
  return fn
}


const Get2 = (url: string) => {
  const fn: MethodDecorator = (target, propertyKey, descriptor: PropertyDescriptor) => {
    axios.get(url).then(res => {
      // 在这里取出所存元数据的 key 所存的 value(字符串 result) ,看返回的数据中有没有这个值,有的话直接返回
      const k = Reflect.getMetadata('key', target)
      
      descriptor.value(k ? res.data[k] : res.data)
    })
  }
  return fn
}
class Http4 {
  @Get2('https://api.apiopen.top/api/getHaoKanVideo?page=1&size=10')

  // 比如:对这里的 参数data 使用装饰器 Result,目的是自动取出 data 中的 result 属性
  // @Result 优先于 @Get2 先执行,在 @Result 存元数据,在 @Get2 中取元数据
  getList(@Result() data: any) {
    console.log(data)
  }
}

经过参数装饰器后,打印出的 data:

在这里插入图片描述

四、属性装饰器 PropertyDecorator

  • 属性 的装饰器,在属性前 @DecoratorName
  • 属性装饰器需要定义为 PropertyDecorator 类型
  • 属性装饰器回传参数:target, propertyKey
    • target:调用者的 原型
    • propertyKey: 调用者的 属性名字
const Color: PropertyDecorator = (target, propertyKey) => {
  // 【target】:{constructor: ƒ} 
  // 【propertyKey】:color
  
  // 一些操作...
}
class Http5 {
  // 对 属性color 使用 属性装饰器Color
  @Color
  color:string
  constructor () {
    this.color = 'blue'
  }
}

看的时候很懵逼,一定要多敲才能理解深刻!!

如果只看文章太痛苦,可以看文章最上面引言中提到的B站视频教程,然后再敲一遍

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/623885.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

NFTScan | 05.29~06.04 NFT 市场热点汇总

欢迎来到由 NFT 基础设施 NFTScan 出品的 NFT 生态热点事件每周汇总。 周期:2023.05.29 ~ 2023.06.04 NFT Hot News:NFT 热点资讯 01/ 数据:NFT 巨鲸 Pranksy 以 52.17 枚 ETH 抛售 25 枚 Doodles 5 月 29 日,据 NFT Whale Aler…

Java + lua

luaj 主要特征 luaj 用法示例 luaj 实现原理 查找并调用指定的 Java 方法 从 Java 方法获取返回值 将 Lua function 作为参数传递给 Java 方法 在某些业务场景下,我们可能会遇到 lua 中要调用 java 代码情况,当然这个用 JNI 肯定是可以做到的&…

三十六、数学知识——组合数(递推法 + 预处理法 + 卢卡斯定理 + 分解质因数求解组合数 + 卡特兰数)

组合数算法主要内容 一、基本思路1、组合数基本概念2、递推法——询问次数多 a b 值较小 模处理(%mod)3、预处理阶乘方法——询问次数较多 a b 值很大 模处理(%mod)4、卢卡斯定理——询问次数较少 (a b 值很大&am…

泰克AFG31051信号发生器产品参数

AFG31000系列任意波函数发生器 概述 验证连接 DUT 后输出波形 InstaView? 技术用在任意波函数发生器上可直接查看连接 DUT 后的实时波形,无需使用示波器或其他设备,节省测试时间并避免因阻抗不匹配导致的实验错误。 高保真度信号与高级模式 在连续模式…

软考高级架构师笔记-6计算机系统性能评价信息系统基础知识

目录 1. 前言 & 考情分析2. 系统配置与性能评价1. 性能指标2. 性能指标3. 阿姆达尔解决方案3.信息系统基础知识1.信息系统的分类2.信息系统的生命周期3.信息系统战略规划3.常见系统介绍1.客户关系管理CRM2.供应链管理SCM3.企业应用集成EAI4.结语1. 前言 & 考情分析 前…

VR全景创业是否真的赚钱?项目真的靠谱吗?

说到创业,也许你心里会觉得这类项目对于技术和资金等要求都是比较高的,先别急着反驳,这是大多数人的心理。我们选择某个创业项目时,都需要从创业成本和盈利利润来做预算,现在告诉你有一个VR全景创业项目,几…

爆火的AIGC到底是一片新蓝海,还是又一次的泡沫?

自ChatGPT发布以来,陷入了AIGC热,无论是大众的讨论、资本的流向还是大厂的加入,AIGC似乎都会是未来几年内最火的新蓝海。 不同于以往的“顶尖科技”泡沫,AIGC是真正可以应用到生活中的,这也是为何它会引发大量“失业论…

操作系统 复习--实训题

一. 简答题(共8题,100分) 1. (简答题) 编程使用fork()函数创建子进程,要求父进程中打印当前进程的 PID 和子进程的 PID,而在子进程中只打印当前进程的 PID。 参考代码: int main() { pid_t child_pid;c…

使用openlayers加载geoserver发布的arcgis瓦片

openlayers版本:6.5 geoserver版本:2.18.0 1. geoserver发布arcgis瓦片 首先去maven上面找最新的gwc-arcgiscache https://mvnrepository.com/artifact/org.geowebcache/gwc-arcgiscache/1.19.1 把这个jar包下载下来放到目录geoserver/WEB-INF/lib下面…

可扩展性与生态应用:Ardor公链AMA回顾

近日,Jelurida团队工程师Francisco Sarrias做客CryptoWallet.com,分享了一些有关Ardor的话题: Ardor是什么? Ardor是一个旨在提高区块链可扩展性的开源平台,这意味着该项目有助于使区块链网络运行更顺畅,用…

10分钟通过云服务器搭建自己的chatGPT镜像服务

通过云服务器搭建自己的chatGPT镜像服务 前提:需要有自己的API KEY 1 购买云服务器 本教程以阿里云的云服务器为例。 阿里云地址:https://www.aliyun.com/?spm5176.28008736.J_3207526240.1.769d3e4dTtNjuI 进入阿里云官网,选择云服务器ECS进…

精选博客系列|VMware如何实现多云基础设施

私有云,公有云,多云,边缘云… 如今,组织的团队、数据和工作负载分布在各种环境中。毫无疑问,这导致了技术上的复杂性增加、安全风险加剧、成本飙升和云战略不连贯的问题。 “39% 的高管难以在(他们的&…

18.4:打印一个字符串的全部排列

打印一个字符串的全部排列 方法一&#xff1a;暴力方法。 //方法一&#xff1a;暴力方法。public static List<String> permutation1(String s) {//str是一个存储字符类型的有序表。ArrayList<Character> str new ArrayList<>();//将字符串中的类型存储在s…

Zookeeper概述

​ ZooKeeper概述 ZooKeeper是什么 zookeeper是一个为分布式应用程序提供的一个分布式开源协调服务框架。是Google的Chubby的一个开源实现&#xff0c;是Hadoop和Hbase的重要组件。主要用于解决分布式集群中应用系统的一致性问题。提供了基于类似Unix系统的目录节点树方式的数…

docker 安装 nsq

一. nsq介绍 nsq介绍 NSQ是一个基于Go语言&#xff0c;由bitly公司开源出来的一款简单易用的消息中间件。 官方和第三方开发了众多客户端功能库&#xff0c;如基于HTTP的nsqd、Go客户端go-nsq、Python客户端pynsq、基于Node.js的JavaScript客户端nsqjs、异步C客户端libnsq、J…

JavaSE-02【类型转换和运算符】

第一章&#xff1a;数据类型转换 Java程序中要求参与计算的数据&#xff0c;必须要保证数据类型的一致&#xff0c; 如果数据类型不一致则发生类型的转换1.1 自动转换 自动转换&#xff1a;将取值范围小的类型自动提升为取回范围大的类型 自动类型转换原理&#xff1a;一个i…

MySql锁知识记录积累(一)

1.关于脏读、幻读和不可重复读 脏读&#xff1a;一个事务A读取到了另一个事务B未提交的数据&#xff0c;叫做脏读 不可重复读&#xff1a;事务A被事务B干扰到了&#xff01;在事务A范围内&#xff0c;两个相同的查询&#xff0c;读取同一条记录&#xff0c;却反返回了不同的结…

运行一个新vue项目踩坑

npm install报错了&#xff0c;主要是因为node版本太高了。去node官网&#xff0c;下载低版本的msi后缀的文件&#xff0c;运行安装。在vs code里&#xff0c;npm下载依赖&#xff0c;并运行即可。 1. 无法cnpm cnpm : 无法加载文件 D:\Program Files\nodejs\node_global\cnpm.…

前端放大镜效果实现

放大镜效果实现 放大图片的需求&#xff0c;一般是在原有的渲染之上&#xff0c;额外添加一个放大框&#xff0c;当鼠标在原图上移动&#xff0c;放大框内就以当前的鼠标为中心&#xff0c;局部放大一定范围&#xff0c;在淘宝商城中是常有的实现。下面将用两种实现。 1、使用d…

是德 DSOX1202A示波器技术参数

KEYSIGHT是德科技 lnfiniiVision 1000 X 系列示波器是具有专业级功能的入门级示波器&#xff0c;配备的联网软件可提供远程控制和数据记录等功能。 它集 6 种仪器的功能于一身&#xff0c;属于是德科技智能测试台必备仪器之一。该系列包含 4 款独具特长的仪器&#xff0c;通过同…