装饰器定义
- 装饰器是一种特殊类型的声明,它能够被附加到类声明、方法、属性或参数上,可以修改类的行为
- 常见的装饰器有类装饰器、属性装饰器、方法装饰器和参数装饰器
-
类装饰器
类装饰器在类声明之前声明,用来监控、修改或替换类定义
- 参数是类的定义或者构造函数
代码示例
基本的装饰器
export {};
// 类的装饰器,参数target是类的构造函数本身
interface Animal {
swings: number;
fly: () => {};
}
function flyable(target: any) {
console.log(target);
target.prototype.swings = 2;
target.prototype.fly = function () {
console.log("我能飞");
};
}
@flyable
class Animal {
constructor() {}
}
let animal: Animal = new Animal();
console.log(animal.swings);
animal.fly();
类的装饰器工厂
// 类的装饰器工厂,可以传递不同参数值,参数target是类的构造函数本身
interface Animal {
swings: number;
fly: () => {};
}
function flyable(swings: number) {
return function flyable(target: any) {
console.log(target);
target.prototype.swings = swings;
target.prototype.fly = function () {
console.log("我能飞");
};
};
}
@flyable(4)
class Animal {
constructor() {}
}
let animal: Animal = new Animal();
console.log(animal.swings);
animal.fly();
多种类型的装饰器方法
// 实例属性的装饰器,target是类原型对象,key是属性的名字
function instancePropertyDecorator(target, key) {
target.protoName = "这是类实例上的属性";
console.log("instancePropertyDecorator", target, key);
}
// 类的静态属性,target是类的构造函数,key是属性名
function classPropertyDecorator(target, key) {
console.log("classPropertyDecorator", target, key);
}
// 实例方法,target是类的原型,key是方法名,descriptor属性描述符
function instanceMethodDecorator(target, key, descriptor) {
console.log("instanceMethodDecorator", target, key, descriptor);
}
function classMethodDecorator(target, key, descriptor) {
console.log("classMethodDecorator", target, key, descriptor);
}
interface Person {
instanceProperty: string;
protoName: string;
}
class Person {
// 实例的属性装饰器
// 实例的属性装饰器
@instancePropertyDecorator
instanceProperty!: string; //实例属性
//实例属性
// 类的属性装饰器
@classPropertyDecorator
static classProperty: string; //类的静态属性
// 实例的方法装饰器
@instanceMethodDecorator
instanceMethod() {
//实例的方法
}
// 类的方法装饰器
@classMethodDecorator
classMethod() {}
}
let p = new Person();
console.log(Person.prototype.protoName);
console.log(p.protoName);
数据埋点的运用
function before(beforeFn) {
return function (target, methodName, descriptor) {
let oldMethod = descriptor.value;
descriptor.value = function () {
beforeFn.apply(this, arguments);
return oldMethod.apply(this, arguments);
};
};
}
function after(afterFn) {
return function (target, methodName, descriptor) {
let oldMethod = descriptor.value;
descriptor.value = function () {
let result = oldMethod.apply(this, arguments);
afterFn.apply(this, arguments);
return result;
};
};
}
class App extends Component {
@before(() => console.log("before"))
onClickBefore() {
console.log("beforeClick");
}
@after(() => console.log("after"))
onClickAfter() {
console.log("afterClick");
}
@after(() => fetch("/api/json"))
ajaxClick() {
console.log("ajax data");
}
render() {
return (
<div>
<button onClick={this.onClickBefore}> beforeClick</button>
<button onClick={this.onClickAfter}>afterClick</button>
</div>
);
}
}
表单数据校验的运用
// 表单校验
Function.prototype.before = function (beforeFn) {
let thisFn = this;
return function () {
let pass = beforeFn();
if (pass) {
thisFn.apply(this, arguments);
}
};
};
function registerFn(event) {
console.log("提交表单");
}
registerFn = registerFn.before(function () {
let username = document.getElementById("username").nodeValue;
if (!username) {
return alert("用户名有无");
}
return true;
});