如何在 TypeScript 中使用属性装饰器?
装饰器在TypeScript中具有对类定义过程的编程访问权限。
请记住,类描述列出了类的属性、指定的方法和结构。创建类实例时,该类实例可以访问这些属性和方法。但是,在创建类实例之前,装饰器允许我们在类的定义中添加代码。它们等同于 C# 属性或 Java 注解。
装饰器是一个具有特定参数集的函数。JavaScript 运行时会自动填充这些参数,这些参数提供有关已应用装饰器的类、方法或属性的信息。参数的类型和数量决定了装饰器可以在哪里使用。
装饰器是 TypeScript 编译器的实验性功能,从 ES5 开始支持。要使用装饰器,必须在 tsconfig.json 文件中启用编译选项。该选项的名称为 ExperimentalDecorators,需要将其设置为 true。
装饰器允许通过用适当的功能和值封装现有代码来进行修改。目前仅支持一个类及其部分 -
- 类本身
- 类方法
- 类属性
- 类的对象访问器(getter 和 setter)
- 类方法参数
我们将只关注类属性。
TypeScript 中的属性装饰器
属性装饰器是在属性声明之前声明的。声明文件或环境上下文无法使用属性装饰器(例如在 declare class 中)。相反,使用称为属性装饰器的函数来装饰我们类中的属性声明。
有了这些知识,我们可以做一些有趣的事情,例如更改默认定义或通过添加新属性或更改数据来修改我们的对象实例。它接收类的构造函数和属性名称作为参数。
使用属性装饰器
在运行时将属性装饰器表达式作为函数调用时,将向其传递以下两个参数 -
- 实例成员的类原型或静态成员的类构造函数方法。
- 成员的名称。
语法
用户可以按照以下语法在 TypeScript 中创建属性装饰器
//syntax to create decorator Class Class_Name{ @Decorator_Name(argument) // Code of Components }
如上语法所示,我们将在类中创建装饰器的名称和参数值。
示例
首先,我们创建一个名为“Person”的类。此类有两个属性,username 和 greet,我们将其记录到控制台。我们将使用装饰器通过添加参数中提供的发送者姓名来修改 username 属性。请参见下面的类 -
class Person { @UpdatedMessage("ABC") username: string; greet: string; }
对于Person类的username属性,我们在此实例中使用了装饰器UpdatedMessage。它将在运行时使用提供的参数调用 UpdatedMessage 函数。它应该生成一个函数来操作 username 属性。我们返回的函数需要两个参数。当我们想要获取 username 或将 username 设置为新值时,将触发 getter 和 setter 函数。
然后将使用 Object.defineProperty 函数。它用于为项目提供特定属性。
有三个要求 -
对象的实例 - 将添加属性的对象。在我们的场景中,target 变量包含 Greeter 类的实例。
propertyName - 属性的名称。
配置对象 - 它是一个具有定义属性的项目。在我们的示例中,我们将 getter 和 setter 函数作为规范添加。
此函数将用 updatedMessage 替换当前的 username 属性。现在我们将结合所有步骤,装饰器就可以使用了。请参见以下代码 -
function UpdatedMessage(sender: string) { return function (target: any, propertyKey: string){ let updatedmessage: string // Return modifiedMessage whenever the message is asked const getter = function () { return updatedmessage } // Set the modifiedMessage value const setter = function () { updatedmessage = `Hi ${sender}!` } // Overwrite the original message with modifiedMessage we just created Object.defineProperty(target, propertyKey, { get: getter, set: setter, }) } } class Person { // Modify message property using decorator @UpdatedMessage('ABC') username: string greet: string constructor() { this.username = 'Hi there!' this.greet = 'Welcome to tutorialsPoint' } message() { console.log(`${this.username}`) console.log(`${this.greet}`) } } let Greetings = new Person() Greetings.message()
编译后,它将生成以下 JavaScript 代码 -
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; function UpdatedMessage(sender) { return function (target, propertyKey) { var updatedmessage; // Return modifiedMessage whenever the message is asked var getter = function () { return updatedmessage; }; // Set the modifiedMessage value var setter = function () { updatedmessage = "Hi " + sender + "!"; }; // Overwrite the original message with modifiedMessage we just created Object.defineProperty(target, propertyKey, { get: getter, set: setter }); }; } var Person = /** @class */ (function () { function Person() { this.username = 'Hi there!'; this.greet = 'Welcome to tutorialsPoint'; } Person.prototype.message = function () { console.log("" + this.username); console.log("" + this.greet); }; __decorate([ UpdatedMessage('ABC') ], Person.prototype, "username"); return Person; }()); var Greetings = new Person(); Greetings.message();
输出
以上代码将产生以下输出 -
Hi ABC! Welcome to tutorialsPoint
因此,我们看到我们可以在类的属性上使用装饰器并对其进行操作。装饰器帮助我们创建更易读和灵活的代码。