C/C++教程

【九月打卡】第9天 TypeScript学习 10-9~10-10章

本文主要是介绍【九月打卡】第9天 TypeScript学习 10-9~10-10章,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

课程名称: 晋级TypeScript高手,成为抢手的前端开发人才

课程章节: 10-9~10-10 【泛型工厂类继承装饰器】 泛型工厂类继承装饰器实现

课程讲师: keviny79

课程内容:

类装饰器的应用场景:
需求:对已经开发好的项目中的任何一个类,创建实例时,打印日志信息,输出哪一个类被创建了,并输出传递了哪些参数信息。
代码实现:

/*
需求:对已经开发好的项目中的任何一个类,创建实例时,
打印日志信息, 输出哪一个类被创建了,并输出传递了哪些参数信息
*/

//  1.完成日志信息的装饰器
function LoggerInfoDecorator<T extends { new (...args: any): any }>(
  targetClass: T
) {
  class LoggerSonClass extends targetClass {
    constructor(...args: any) {
      super(...args);
      console.log("日志信息...targetClass:", targetClass);
    }
  }

  return LoggerSonClass;
}

// 2. 目标类
@LoggerInfoDecorator
class Test {
  name!: string;
  age!: number;
  // 1.先执行原来构造函数
  constructor(name: string) {
    this.name = name;
  }
  eat() {
    console.log(this.name, "吃饭");
  }
}

let test = new Test("aa");

分析:

以下是需求实现的步骤

1.我们需要在“使用”类的时候,进行日志的打印,而不是没有使用类就进行日志的打印,如下:(以下代码是错误的)

//  1.完成日志信息的装饰器
function LoggerInfoDecorator(
  targetClass: any
) {
  console.log("日志信息...targetClass:", targetClass.name);
}

// 2. 目标类
@LoggerInfoDecorator
class Test {
  name!: string;
  age!: number;
  // 1.先执行原来构造函数
  constructor(name: string) {
    this.name = name;
  }
  eat() {
    console.log(this.name, "吃饭");
  }
}

//这里没有执行 类,但还是打印了日志信息,是不对的
// let test = new Test("aa");

2.如何做?根据阅读 类装饰器源码,可以知道 类装饰器 最后会返回一个类,后覆盖掉 “目标类”,在把覆盖掉的 类名 导出,之后创建 “目标类” 就会是被覆盖掉的类,如下:

// 2. 目标类
var Test = /** @class */ (function () {
    // 1.先执行原来构造函数
    function Test(name) {
        this.name = name;
    }
    Test.prototype.eat = function () {
        console.log(this.name, "吃饭");
    };
    // __decorate() 装饰器的返回值会 赋值给 Test 类,最后导出
    Test = __decorate([
        LoggerInfoDecorator,
        __metadata("design:paramtypes", [String])
    ], Test);
	// 导出
    return Test;
}());

3.利用第2点,我们就可以在“类装饰器中”创建一个“类”,这个“类”专门用于打印 “日志”,之后返回这个类。在“外界 ”创建目标类时,实际是创建“类装饰器中”自己创建的类,如下:(以下代码是错误的)

function LoggerInfoDecorator(
  targetClass: any
) {
  class LoggerSonClass {
    constructor(...args: any) {
      console.log("日志信息...targetClass:");
    }
  }

  return LoggerSonClass;
}

// 2. 目标类
// 这里会提示错误
@LoggerInfoDecorator
class Test {
  name!: string;
  age!: number;
  // 1.先执行原来构造函数
  constructor(name: string) {
    this.name = name;
  }
  eat() {
    console.log(this.name, "吃饭");
  }
}

let a = new Test("aa");

4.第3点中的代码是错误的(在js中正确),在阅读源码得知 “类装饰器”中返回的内容最后会赋值给“目标类”,但在ts 中“类装饰器”返回的内容和赋值给“目标类”的内容类型不一样,ts会提示缺少属性。也就是说等号(=)右边必须完全具备 等号(=) 左边的所有属性。

class Test {
  name!: string;
}
class targetClass{
  age!: string;
}
let copy = Test;
// 错误,右侧属性中缺少左侧的属性
copy = targetClass;
//---------------分割线-------------------
class Test {
  name!: string;
}
class targetClass{
  age!: string;
  name!: string;
}
let copy = Test;
// 正确,右侧属性中包含左侧的属性
copy = targetClass;
//---------------分割线-------------------
class Test {
  name!: string;
}
// 这里使用继承可以得到的获取父类中的属性
class targetClass extends Test{
  age!: string;
}
let copy = Test;
// 正确,右侧属性中包含左侧的属性
copy = targetClass;

5.根据第4点可以得知 使用继承 就可以获取父类中属性,之后在把子类赋值给父类就不会出错,所以需求就可以使用类继承完美实现,如下:

//  1.完成日志信息的装饰器
// 这里需要使用 泛型约束为 构造函数
function LoggerInfoDecorator<T extends { new (...args: any): any }>(
  targetClass: T
) {
  // targetClass实际上就是目标类
  class LoggerSonClass extends targetClass {
    constructor(...args: any) {
      super(...args);
      console.log("日志信息...targetClass:", targetClass);
    }
  }
  
  // 返回类,这里返回的类会覆盖掉目标类
  return LoggerSonClass;
}

// 2. 目标类
@LoggerInfoDecorator
class Test {
  name!: string;
  age!: number;
  // 1.先执行原来构造函数
  constructor(name: string) {
    this.name = name;
  }
  eat() {
    console.log(this.name, "吃饭");
  }
}
// 这里创建的 类 实际上是“类装饰器”中返回的类
let test = new Test("aa");

以上就是这个需求的 实现分析。(写的比较乱)

课程收获:
这两章对“类装饰器”的应用场景和有了一些理解。
理解了"泛型工厂类继承装饰器" 实现 和 意义。
图片描述

这篇关于【九月打卡】第9天 TypeScript学习 10-9~10-10章的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!