如何在 TypeScript 中使用属性装饰器?
TypeScript 中的装饰器可以通过编程方式访问类定义过程。
请记住,类描述列出了类的属性、指定方法和结构。类实例在创建时即可访问这些属性和方法。但是,在创建类实例之前,装饰器允许我们将代码添加到类的定义中。它们相当于 C# 的属性或 Java 的注解。
装饰器是一个具有特定参数集的函数。JavaScript 运行时会自动填充这些参数,这些参数提供有关应用了装饰器的类、方法或属性的信息。参数的类型和数量决定了装饰器的使用场景。
装饰器是 TypeScript 编译器的一项实验性功能,从 ES5 开始受支持。要使用装饰器,必须在 tsconfig.json 文件中启用编译选项。该选项名为 ExperimentalDecorators,需要设置为 true。
装饰器 允许通过将现有代码封装为适当的功能和值来进行修改。目前仅支持一个类及其各个部分 -
- 类本身
- 类方法
- 类属性
- 类的对象访问器(Getter 和 Setter)
- 类方法参数
我们将只关注类属性。
TypeScript 中的属性装饰器
在属性声明之前,会声明一个属性装饰器。声明文件或环境上下文不能使用属性装饰器(例如在声明类中)。相反,我们使用一个称为属性装饰器的函数来装饰类中的属性声明。
有了这些知识,我们可以做一些有趣的事情,例如更改默认定义或通过添加新属性或更改数据来修改对象实例。它接收类的构造函数和属性名称作为参数。
使用属性装饰器
当在运行时将属性装饰器表达式作为函数调用时,以下两个参数将传递给它:
- 实例成员的类原型或静态成员的类构造函数方法。
- 成员的名称。
语法
用户可以按照以下语法在 TypeScript 中创建属性装饰器
//创建装饰器的语法 Class Class_Name{ @Decorator_Name(argument) // 组件代码 }
如上语法所示,我们将在类中创建装饰器的名称和参数值。
示例
首先,我们创建一个名为"Person"的类。该类有两个属性:username 和 greet,我们将在控制台中登录它们。我们将使用装饰器通过添加参数中提供的发送者名称来修改 username 属性。参见下面的类 -
class Person { @UpdatedMessage("ABC") username: string; greet: string; }
对于 Person 类的 username 属性,我们在此实例中使用了装饰器 UpdatedMessage。使用提供的参数,它将在运行时调用一个 UpdateMessage 函数。该函数应该生成一个用于操作 username 属性的函数。我们返回的函数需要两个参数。当我们想要获取用户名或将用户名设置为新值时,将触发 getter 和 setter 函数。
然后会使用 Object.defineProperty 函数。该函数用于赋予项目特定的属性。
有三个要求 -
对象的实例 - 将添加属性的对象。在我们的场景中,目标变量包含 Greeter 类的一个实例。
propertyName − 属性的名称。
配置对象 − 它是一个具有已定义属性的项目。我们将在示例中添加 getter 和 setter 函数作为规范。
此函数将用 updatedMessage 替换当前的 username 属性。现在我们将所有步骤合并起来,装饰器就可以使用了。请参阅以下代码 −
function UpdatedMessage(sender: string) { return function (target: any, propertyKey: string){ let updatedmessage: string // 每当询问消息时返回modifiedMessage const getter = function () { return updatedmessage } // 设置modifiedMessage值 const setter = function () { updatedmessage = `Hi ${sender}!` } // 用我们刚刚创建的modifiedMessage覆盖原始消息 Object.defineProperty(target, propertyKey, { get: getter, set: setter, }) } } class Person { // 使用装饰器修改消息属性 @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; // 每当询问消息时返回modifiedMessage var getter = function () { return updatedmessage; }; // 设置modifiedMessage值 var setter = function () { updatedmessage = "Hi " + sender + "!"; }; // 用我们刚刚创建的modifiedMessage覆盖原始消息 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
由此,我们了解到,我们可以在类的属性上使用装饰器并对其进行操作。装饰器帮助我们创建更易读、更灵活的代码。