vue-class-component 是一个用于在 Vue.js 中使用类风格组件的库。它允许你使用 TypeScript 装饰器来定义 Vue 组件,使代码更加简洁和可维护。结合vue-property-decorator 社区库使用常用的装饰器,例如 @Prop、@Watch等。
定义
装饰器(Decorator)是 TypeScript 和 JavaScript 中的一种特殊语法,用于修改类、方法、属性或参数的行为。装饰器可以看作是一个函数,它可以在不修改原始代码的情况下,动态地为代码添加功能。
装饰器的类型
- 类装饰器:用于类声明之前,应用于类构造函数,可以用来监视、修改或替换类定义。
- 方法装饰器:用于方法声明之前,应用于方法的属性描述符,可以用来监视、修改或替换方法定义。
- 访问器装饰器:用于访问器(getter/setter)声明之前,应用于访问器的属性描述符。
- 属性装饰器:用于属性声明之前,应用于类的属性。
- 参数装饰器:用于参数声明之前,应用于方法的参数。
应用
tsconfig.json中需要开启这两项
"experimentalDecorators": true,
"emitDecoratorMetadata": true
介绍五种装饰器
1. 类装饰器
类装饰器用于类声明之前,应用于类构造函数,可以用来监视、修改或替换类定义。
入参
类装饰器只有一个入参,即被装饰的类的构造函数。
应用场景
添加或修改类的属性和方法: - 可以在类的原型上添加新的属性或方法,或者修改现有的属性和方法。
依赖注入: - 可以在类实例化时注入依赖,常用于依赖注入框架。
元数据添加: - 可以为类添加元数据,用于描述类的行为或属性。
类的替换: - 可以返回一个新的构造函数,从而替换原有的类。
下面示例使用的场景是添加或修改类的属性和方法
interface Person {
school: string;
identity: string;
}
@HighSchool()
class Person {}
type optionsType = {
identity?: string;
school?: string;
};
function HighSchool(options: optionsType = {}) {
return function (target: any) {
target.prototype.identity =
options.identity ?? "senior high school student";
target.prototype.school = options.school ?? "北京市第三中学";
};
}
const p = new Person();
console.log(p.identity); // 输出 senior high school student
console.log(p.school); // 输出北京市第三中学
2.方法装饰器
入参
方法装饰器有三个入参,分别是:
target:被装饰方法所属的类的原型对象(对于实例方法)或类的构造函数(对于静态方法)。propertyKey:被装饰方法的名称。descriptor:被装饰方法的属性描述符。
应用场景
日志记录:在方法调用前后记录日志,方便调试和监控。
性能监控:记录方法的执行时间,帮助优化性能。
权限控制:在方法执行前检查用户权限,确保只有授权用户才能执行某些操作。
输入验证:在方法执行前验证输入参数的合法性,防止错误输入。
节流和防抖:控制方法的调用频率,防止频繁调用导致性能问题。
缓存:缓存方法的返回值,避免重复计算,提高性能。
事务管理:在方法执行前后管理事务,确保数据的一致性和完整性。
下面示例实现了装饰器节流
function Throttle(wait: number, options: any = {}) {
return function (
target: any,
propertyKey: string,
descriptor: PropertyDescriptor
): void {
const originalMethod = descriptor.value;
let timer: any = null;
descriptor.value = function (...args: any[]) {
if (timer) {
options.waitFn && options.waitFn();
return;
}
timer = setTimeout(() => {
originalMethod.apply(this, args);
timer = null;
}, wait);
};
};
}
class Person {
@Throttle(3000, {
waitFn: () => {
console.log("还不饿");
},
})
eat(food: string = "apple") {
console.log("eat", food);
}
}
const highSchool = new Person();
setInterval(() => {
highSchool.eat();
}, 1000);
实现了节流,输出如下:
3.访问器修饰符
入参
被装饰访问器所属的类的原型对象(对于实例访问器)。
对于静态访问器,则是类的构造函数。
在示例中,[`target`](<> "Go to definition") 是 [`Person.prototype`](<> "Go to definition")。
被装饰访问器的名称。在示例中,[`propertyKey`](<> "Go to definition") 是 `"money"`。
被装饰访问器的属性描述符。属性描述符是一个对象,包含以下属性:
[`get`](<> "Go to definition"):访问器的 getter 方法。
[`set`](<> "Go to definition"):访问器的 setter 方法。
`enumerable`:是否可以枚举属性。
`configurable`:是否可以删除或修改属性的属性描述符。
在示例中,descriptor 包含 get 和 set 方法。
class Person {
_money: number = 100;
@logAccess()
get money() {
return this._money;
}
set money(value: number) {
this._money = value;
}
}
function logAccess() {
return function (
target: any,
propertyKey: string,
descriptor: PropertyDescriptor
) {
const originalGet = descriptor.get;
const originalSet = descriptor.set;
if (originalGet) {
descriptor.get = function () {
console.log(`Getting value of ${propertyKey}`);
return originalGet.apply(this);
};
}
if (originalSet) {
descriptor.set = function (value: any) {
console.log(`Setting value of ${propertyKey} to ${value}`);
originalSet.apply(this, [value]);
};
}
};
}
const highSchool = new Person();
const getMoney = highSchool.money; // get Getting value of money
highSchool.money = 50; // Setting value of money to 50
4.属性修饰符
入参
target:被装饰属性所属的类的原型对象(对于实例属性)或类的构造函数(对于静态属性)。propertyKey:被装饰属性的名称。
5.参数修饰符
入参
target:被装饰参数所属的方法的类的原型对象(对于实例方法)或类的构造函数(对于静态方法)。
propertyKey:被装饰参数所属的方法的名称。
parameterIndex:被装饰参数在方法参数列表中的索引。