理解 TypeScript 装饰器的关键是了解它们可以附加到类、方法、属性、参数等各种元素上,以修改它们的行为。以下是一些具体的 TypeScript 装饰器案例:
1. 类装饰器:添加元数据
类装饰器可以用来添加元数据或修改类的行为。例如,让我们创建一个用于标记类的装饰器,它会记录类的名称和一些元数据。
function classDecorator<T extends { new (...args: any[]): {} }>(constructor: T) {
return class extends constructor {
className = constructor.name;
};
}
@classDecorator
class MyClass {
constructor(public data: string) {}
}
const instance = new MyClass("Hello");
console.log(instance.className); // 输出 "MyClass"
2. 方法装饰器:修改方法行为
方法装饰器可以用来修改方法的行为。以下示例演示如何创建一个方法装饰器,用于限制方法的执行次数。
function limitExecutions(limit: number) {
return function (
target: any,
key: string,
descriptor: PropertyDescriptor
) {
const originalMethod = descriptor.value;
let executions = 0;
descriptor.value = function (...args: any[]) {
if (executions < limit) {
executions++;
return originalMethod.apply(this, args);
} else {
console.log(`Method ${key} reached execution limit.`);
}
};
return descriptor;
};
}
class Example {
@limitExecutions(2)
execute() {
console.log("Method executed.");
}
}
const instance = new Example();
instance.execute(); // 输出 "Method executed."
instance.execute(); // 输出 "Method executed."
instance.execute(); // 输出 "Method reached execution limit."
3. 属性装饰器:添加元数据
属性装饰器用于添加元数据或修改属性的行为。以下示例创建一个属性装饰器,用于添加属性的描述信息。
function propertyDescription(description: string) {
return function (target: any, key: string) {
Reflect.defineMetadata("description", description, target, key);
};
}
class Example {
@propertyDescription("This is a sample property.")
data: string;
}
const description = Reflect.getMetadata("description", Example.prototype, "data");
console.log(description); // 输出 "This is a sample property."
4. 参数装饰器:验证参数
参数装饰器可以用来验证方法的参数。以下示例演示如何创建一个参数装饰器,用于检查参数是否为正数。
function positiveNumber(target: any, key: string, index: number) {
const originalMethod = target[key];
target[key] = function (...args: any[]) {
if (typeof args[index] !== "number" || args[index] <= 0) {
console.log(`Invalid argument at position ${index}: ${args[index]}`);
} else {
return originalMethod.apply(this, args);
}
};
}
class Example {
add(@positiveNumber a: number, @positiveNumber b: number) {
return a + b;
}
}
const instance = new Example();
instance.add(5, 10); // 输出 15
instance.add(-2, 10); // 输出 "Invalid argument at position 0: -2"
5. 计时装饰器:记录方法执行时间
function timing(target: any, key: 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(`Method ${key} took ${end - start} milliseconds.`);
return result;
};
return descriptor;
}
class Timer {
@timing
slowOperation() {
for (let i = 0; i < 10000000; i++) {}
}
}
const timer = new Timer();
timer.slowOperation(); // 输出方法执行时间
6. 验证装饰器:验证输入参数
function validate(target: any, key: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
if (args.some(arg => typeof arg !== "number")) {
console.error("Invalid argument type. Must be a number.");
return;
}
return originalMethod.apply(this, args);
};
return descriptor;
}
class Calculator {
@validate
add(a: number, b: number) {
return a + b;
}
}
const calculator = new Calculator();
calculator.add(5, 10); // 输出 15
calculator.add(5, "10"); // 输出 "Invalid argument type. Must be a number."
7. 记录日志装饰器:记录方法调用日志
function log(target: any, key: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(`Calling method ${key} with arguments: ${args}`);
return originalMethod.apply(this, args);
};
return descriptor;
}
class Logger {
@log
logMessage(message: string) {
console.log(message);
}
}
const logger = new Logger();
logger.logMessage("Hello, World!"); // 输出方法调用日志
8. 身份验证装饰器:验证用户登录状态
function authenticate(target: any, key: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
// 检查用户是否已登录
if (isUserLoggedIn()) {
return originalMethod.apply(this, args);
} else {
console.error("Authentication failed. Please log in.");
}
};
return descriptor;
}
class AuthenticatedApp {
@authenticate
accessSecureData() {
console.log("Accessing secure data.");
}
}
const app = new AuthenticatedApp();
app.accessSecureData(); // 输出 "Accessing secure data.",因为用户已登录
// 模拟用户未登录
function isUserLoggedIn() {
return false;
}
app.accessSecureData(); // 输出 "Authentication failed. Please log in."
9. 路由装饰器:定义路由信息
function route(path: string) {
return function (target: any, key: string, descriptor: PropertyDescriptor) {
// 将路由信息存储在元数据中
Reflect.defineMetadata("route", path, target, key);
};
}
class RouterExample {
@route("/home")
displayHome() {
// 显示主页
}
@route("/about")
displayAbout() {
// 显示关于页面
}
}
// 获取路由信息
const homeRoute = Reflect.getMetadata("route", RouterExample.prototype, "displayHome");
console.log(homeRoute); // 输出 "/home"
10. 缓存装饰器:缓存方法的结果
function cache(target: any, key: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
const cache = new Map();
descriptor.value = function (...args: any[]) {
const cacheKey = JSON.stringify(args);
if (cache.has(cacheKey)) {
return cache.get(cacheKey);
} else {
const result = originalMethod.apply(this, args);
cache.set(cacheKey, result);
return result;
}
};
return descriptor;
}
class CachedCalculator {
@cache
add(a: number, b: number) {
return a + b;
}
}
const calculator = new CachedCalculator();
console.log(calculator.add(2, 3)); // 输出 5
console.log(calculator.add(2, 3)); // 输出 5(从缓存中获取)
11. 日志装饰器:记录方法执行日志
function logMethod(target: any, key: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(`Calling method ${key} with arguments: ${JSON.stringify(args)}`);
const result = originalMethod.apply(this, args);
console.log(`Method ${key} returned: ${JSON.stringify(result)}`);
return result;
};
return descriptor;
}
class LoggableClass {
@logMethod
performOperation(a: number, b: number) {
return a + b;
}
}
const loggable = new LoggableClass();
loggable.performOperation(3, 7); // 输出方法的执行日志
12. 跟踪装饰器:记录方法执行时间
function trackPerformance(target: any, key: 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(`Method ${key} took ${end - start} milliseconds to execute.`);
return result;
};
return descriptor;
}
class PerformantClass {
@trackPerformance
timeConsumingOperation() {
for (let i = 0; i < 100000000; i++) {}
}
}
const performant = new PerformantClass();
performant.timeConsumingOperation(); // 输出方法的执行时间
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。