typescript 中的装饰器提供了一种强大的机制来修改类、方法、属性和参数的行为。虽然它们看起来像是一种现代的便利,但装饰器植根于面向对象编程中成熟的装饰器模式。通过抽象日志记录、验证或访问控制等常见功能,装饰器允许开发人员编写更清晰、更易于维护的代码。
在本文中,我们将从首要原则探索装饰器,分解其核心功能,并从头开始实现它们。在此过程中,我们将了解一些实际应用程序,这些应用程序展示了装饰器在日常 typescript 开发中的实用性。
什么是装饰器?
在 typescript 中,装饰器只是一个可以附加到类、方法、属性或参数的函数。此函数在设计时执行,使您能够在代码运行之前更改代码的行为或结构。装饰器支持元编程,允许我们在不修改原始逻辑的情况下添加额外的功能。
让我们从一个方法装饰器的简单示例开始,该示例记录调用方法的时间:
function log(target: any, propertykey: string, descriptor: propertydescriptor) { const originalmethod = descriptor.value; descriptor.value = function (...args: any[]) { console.log(`calling ${propertykey} with arguments: ${args}`); return originalmethod.apply(this, args); }; return descriptor; } class example { @log greet(name: string) { return `hello, ${name}`; } } const example = new example(); example.greet('john');
登录后复制
这里,日志装饰器包装了greet方法,在执行之前记录其调用和参数。此模式对于将日志记录等横切关注点与核心逻辑分离非常有用。
装饰器如何工作
typescript 中的装饰器是接受与其所装饰的项目相关的元数据的函数。基于这些元数据(如类原型、方法名称或属性描述符),装饰器可以修改行为甚至替换被装饰的对象。
装饰器的类型
装饰器可以应用于各种目标,每个目标都有不同的目的:
- 类装饰器:接收类构造函数的函数。
function classdecorator(constructor: function) { // modify or extend the class constructor or prototype }
登录后复制
- 方法装饰器:接收目标对象、方法名称和方法描述符的函数。
function methoddecorator(target: any, propertykey: string, descriptor: propertydescriptor) { // modify the method's descriptor }
登录后复制
- 属性装饰器:接收目标对象和属性名称的函数。
function propertydecorator(target: any, propertykey: string) { // modify the behavior of the property }
登录后复制
- 参数装饰器:接收目标、方法名称和参数索引的函数。
function parameterdecorator(target: any, propertykey: string, parameterindex: number) { // modify or inspect the method's parameter }
登录后复制
将参数传递给装饰器
装饰器最强大的功能之一是它们接受参数的能力,允许您自定义它们的行为。例如,让我们创建一个方法装饰器,它根据参数有条件地记录方法调用。
function logconditionally(shouldlog: boolean) { return function (target: any, propertykey: string, descriptor: propertydescriptor) { const originalmethod = descriptor.value; descriptor.value = function (...args: any[]) { if (shouldlog) { console.log(`calling ${propertykey} with arguments: ${args}`); } return originalmethod.apply(this, args); }; return descriptor; }; } class example { @logconditionally(true) greet(name: string) { return `hello, ${name}`; } } const example = new example(); example.greet('typescript developer');
登录后复制
通过将 true 传递给 logconditionally 装饰器,我们确保该方法记录其执行情况。如果我们传递 false,则跳过日志记录。这种灵活性是使装饰器具有多功能性和可重用性的关键。
装饰器的实际应用
装饰器在许多库和框架中都有实际用途。以下是一些值得注意的示例,说明了装饰器如何简化复杂的功能:
- 类验证器中的验证:在数据驱动的应用程序中,验证至关重要。 class-validator 包使用装饰器来简化验证 typescript 类中字段的过程。
import { isemail, isnotempty } from 'class-validator'; class user { @isnotempty() name: string; @isemail() email: string; }
登录后复制
在此示例中,@isemail 和 @isnotempty 装饰器确保电子邮件字段是有效的电子邮件地址并且名称字段不为空。这些装饰器消除了手动验证逻辑的需要,从而节省了时间。
- 使用 typeorm 进行对象关系映射:装饰器广泛用于 typeorm 等 orm 框架中,用于将 typescript 类映射到数据库表。此映射是使用装饰器以声明方式完成的。
import { entity, column, primarygeneratedcolumn } from 'typeorm'; @entity() class user { @primarygeneratedcolumn() id: number; @column() name: string; @column() email: string; }
登录后复制
这里,@entity、@column 和 @primarygeneeratedcolumn 定义了 user 表的结构。这些装饰器抽象了 sql 表创建的复杂性,使代码更具可读性和可维护性。
- angular 依赖注入:在 angular 中,装饰器在管理服务和组件方面发挥着关键作用。 @injectable 装饰器将一个类标记为可以注入其他组件或服务的服务。
@injectable({ providedin: 'root', }) class userservice { constructor(private http: httpclient) {} }
登录后复制
在这种情况下,@injectable 装饰器向 angular 的依赖注入系统发出信号,表明应在全局范围内提供 userservice。这允许跨应用程序无缝集成服务。
实现你自己的装饰器:分解
装饰器的核心就是函数。让我们分解一下从头开始创建装饰器的过程:
类装饰器
类装饰器接收类的构造函数,可以用来修改类原型,甚至替换构造函数。
function addtimestamp(constructor: function) { constructor.prototype.timestamp = new date(); } @addtimestamp class myclass { id: number; constructor(id: number) { this.id = id; } } const instance = new myclass(1); console.log(instance.timestamp); // outputs the current timestamp
登录后复制
方法装饰器
方法装饰器修改方法描述符,允许您更改方法本身的行为。
function logexecutiontime(target: any, propertykey: string, descriptor: propertydescriptor) { const originalmethod = descriptor.value; descriptor.value = function (...args: any[]) { const start = performance.now(); const result = originalmethod.apply(this, args); const end = performance.now(); console.log(`${propertykey} executed in ${end - start}ms`); return result; }; return descriptor; } class service { @logexecutiontime execute() { // simulate work for (let i = 0; i <h4> 物业装修师 </h4> <p>属性装饰器允许您拦截属性访问和修改,这对于跟踪更改非常有用。<br></p> <pre class="brush:php;toolbar:false">function trackChanges(target: any, propertyKey: string) { let value = target[propertyKey]; const getter = () => value; const setter = (newValue: any) => { console.log(`${propertyKey} changed from ${value} to ${newValue}`); value = newValue; }; Object.defineProperty(target, propertyKey, { get: getter, set: setter, }); } class Product { @trackChanges price: number; constructor(price: number) { this.price = price; } } const product = new Product(100); product.price = 200; // Logs the change
登录后复制
结论
typescript 中的装饰器允许您以干净、声明的方式抽象和重用功能。无论您使用验证、orm 还是依赖注入,装饰器都有助于减少样板文件并保持代码模块化和可维护性。从第一原理出发了解它们的工作原理可以更轻松地充分利用它们的潜力并根据您的应用程序定制解决方案。
通过更深入地了解装饰器的结构和实际应用,您现在已经了解了它们如何简化复杂的编码任务并简化各个领域的代码。
以上就是理解 TypeScript 中的装饰器:第一原理方法的详细内容,更多请关注抖狐科技其它相关文章!
-
小红书限流笔记怎么恢复
小红书限流笔记的恢复指南包括:查明笔记被限流的原因;如果违反平台规则,调整笔记内容;如果内容质量低,提升笔记原创性和价值;提交笔记重新发布,等待审核;避免再次违规;善用小红书工具提升笔记质量;寻找其他...
-
脑洞大侦探游艇杀人事件如何通关 游艇杀人事件通关方法
《脑洞大侦探》游艇杀人事件关卡带你进入一场惊心动魄的海上谜案。面对错综复杂的线索和凶手的层层布局,玩家们踏上了揭开真相的征程。php小编香蕉带你深入这段扑朔迷离的案件,抽丝剥茧,探寻凶手的动机和作案手...
-
Win11重置系统失败怎么办 Win11重置系统失败详细解决教程
当您的 windows 11 系统无法重置时,修复电脑问题可能会变得棘手。但不要担心!php小编西瓜在此为您提供了一个详细的指南,将逐步引导您解决重置系统失败的问题。继续阅读,了解导致重置失败的潜在原...
-
华为商城怎么预约购买手机的
如何预约购买华为手机:登录华为商城官网或 app。选择要购买的手机型号。点击“预约购买”。填写预约信息(姓名、联系方式、收货地址)。选择预约时间和门店。确认预约信息并提交。预约成功后前往门店支付并取货...
-
用python怎么爬虫
python网络爬虫 involves using libraries like beautifulsoup, requests, and scrapy to send http requests,...