1类的装饰器
- 装饰器本身就是一个函数
- 装饰器的参数是类的构造函数
- 装饰器是对类本身进行修饰的函数,在类创建好之后立刻执行
- 如果有两个装饰器,他会从下到上执行
function testDecorator(constructor:any){
console.log('装饰器1')
constructor.prototype.getName=()=>{
console.log('ws')
}
}
function testDecorator1(constructor:any){
console.log('装饰器2')
constructor.prototype.getName1=()=>{
console.log('qy')
}
}
@testDecorator
@testDecorator1
class Test{}
let test=new Test();
(test as any).getName()
1.1 工厂函数解决装饰器问题
这种写法可以做一个判断条件去使用装饰器
//装饰器条件
function waysDecorator(flag: boolean) {
if (flag) {
return function (constructor: any) {
constructor.prototype.getName = () => {
console.log("ws");
};
};
} else {
return function (constructor: any) {
constructor.prototype.getName = () => {
console.log("qy");
};
};
}
}
//这里可以根据条件传递不同的参数从而改变我们所需要的装饰器
@waysDecorator(true)
class Ways {}
let ways = new Ways();
(ways as any).getName();
1.2装饰器装饰类
function wsDerator() {
//这里使用一个泛型去继承构造器函数类型
return function <T extends new (...arg: any[]) => any>(constructor: T) {
return class extends constructor {
name = "qy";
getName() {
return this.name;
}
};
};
}
//用装饰器来修饰这个class
const Ws = wsDerator()(
class {
name: string;
constructor(name: string) {
this.name = name;
}
}
);
let ws=new Ws('ws')
ws.getName();
console.log(ws);
2.方法装饰器
- 对于一个普通的方法装饰器taget对应的是类的prototype,key对应的是方法名
- 创建好装饰器就会对类的方法进行装饰
- 静态方法target对应的是类的构造函数
- descriptor可以修改方法的属性,例如方法是否可以被重写,可以对原来的方法进行修改
function deratorGetname(target: any, key: string) {
// console.log(target, key);
}
function deratorAge(target: any, key: string, descriptor:PropertyDescriptor) {
// console.log(target, key,descriptor.value);
descriptor.value= function(){
return 37
}
}
class West {
name: string;
constructor(name: string) {
this.name = name;
}
@deratorGetname
getName() {
return this.name;
}
@deratorAge
static getage() {
return 26;
}
}
const west = new West("ws");
3.访问器的装饰器
function deratorGet(
target: any,
key: string,
descriptor: PropertyDescriptor
) {
console.log(target, key);
descriptor.value=function(){
return'qy'
}
}
class Wast {
private _name: string;
constructor(name: string) {
this._name = name;
}
@deratorGet
get name() {
return this._name;
}
set name(name: string) {
this._name = name;
}
}
const wast = new Wast("ws");
console.log(wast)
4.属性的装饰器
//这里修改的是原型上的name
function nameDeractor(target: any, key: string): any {
target[key] = "ws";
}
class Person {
@nameDeractor
name: string;
//这里的name是定义在类上的
constructor(name: string) {
this.name = name;
}
}
let p1 = new Person("qy");
//这里访问根据原型链他会先找实例上的name
console.log(p1.name);
console.log((p1 as any).__proto__.name);
5.参数装饰器
//第一个参数是原型,第二个是参数名,第三个是参数位置
function paramsDecorator(target: any, key: string, index: number): any {
console.log(target, key, index);
}
class Animal {
getInfo(@paramsDecorator name: string, age: number) {
console.log(name, age);
}
}
let cat = new Animal();
cat.getInfo("xiaohua", 6);
6.装饰器用法
给每一个方法都包裹一个tr catch用于捕获错误
const tip: any = undefined;
//使用工厂模式包裹
function catchDecorator(msg: string) {
return function (target: any, key: string, descriptor: PropertyDescriptor) {
let fn = descriptor.value;
descriptor.value = function () {
try {
fn();
} catch (e) {
console.log(msg);
}
};
};
}
class Question {
@catchDecorator("姓名不存在错误")
getName() {
return tip.name;
}
@catchDecorator("年龄不存在错误")
getAge() {
return tip.age;
}
}
const q1 = new Question();
//这里会报错,需要给每个函数加上一个try catch捕获错误
q1.getName();
q1.getAge();