ค้นหาเว็บไซต์

TypeScript - สืบทอดคอมโพเนนต์สองตัวใน Angular โดยมีคอนสตรัคเตอร์ต่างกัน


นี่ค่อนข้างคล้ายกับการขยายคลาส 2 คลาสใน TypeScript แต่แม้ว่าฉันจะสามารถทำได้ใน TypeScript ฉันก็ไม่สามารถหาวิธีที่ถูกต้องใน Angular ได้

ฉันมีแอป Angular 7 ที่มีคอมโพเนนต์ 1 ตัว บริการ 1 ตัว และคลาสทั่วไป 1 คลาส

ตรงแบบนี้ Stackblitz

ฉันต้องการสร้างคอมโพเนนต์ที่สืบทอดมาจากคลาสของฉัน และคอมโพเนนต์อื่นของฉัน

นี่คือชั้นเรียนของฉัน =>

export class MyClass1<T,O> {
  propertyClass1 = "MyClass1"
  constructor() {
  }

  init(value:string){
    this.propertyClass1 = value;
  }
  sayHelloClass(value:string){console.log('class say'+ value)}
}

นี่คือคอมโพเนนต์ของฉัน =>

export class MyCom1Component implements OnInit {
  propertyComp1 = "MyCom1"
  constructor(private service1:Service1Service) {
      this.propertyComp1 = service1.getProp();
   }

  ngOnInit() {
  }

  sayHelloComponent(value:string){console.log('component say'+ value)}
}

ฉันอยากให้ลูกของฉันขยายบูธ เพื่อที่ฉันจะได้ทำ

  ngOnInit() {
    this.sayHelloClass(this.propertyClass1); // class say MyClass1
    this.init("hoohoho");
    this.sayHelloClass(this.propertyClass1); // class say hoohoho


    this.sayHelloComponent(this.propertyComp1); // component say MyCom1
  }

สิ่งที่ฉันลองทำคือสิ่งนี้ =>

const addMyClassOneInheritance = <T extends new(...args: any[]) => any>(MyCom1Component: T) => {
  return class extends MyCom1Component {
        constructor(...args: any[]) {
            super(...args);
        }
  };
};
const MyMergedClass = addMyClassOneInheritance(MyClass1);
export class ChildComponent extends MyMergedClass<string,number> {
ngOnInit(){
   this.sayHelloClass(this.propertyClass1); // compile ok, execute give a value
   this.sayHelloComponent(this.propertyComp1); // compile ok, execute "can't find sayHelloComponent
}

}

ตัวคอมไพเลอร์ไม่ให้ข้อผิดพลาด แต่เมธอดของคอมโพเนนต์ของฉันไม่ได้ถูกสืบทอด

คำตอบ #1

ฉันขอแนะนำวิธีการที่แตกต่าง ทำให้คลาสสามารถใช้งานกับ DI ได้โดยการระบุด้วย @Injectable

จากนั้นขยายคอมโพเนนต์พ่อแม่ของคุณตามปกติ: ChildComponent extend MyCom1Component และฉีด MyClass1 ของคุณโดยใช้ตัวสร้างของ ChildComponent สุดท้ายเรียกตัวสร้างของพ่อแม่ด้วยอินสแตนซ์ของคลาสที่คุณเพิ่งฉีดเข้าไป

constructor(public myclass1: MyClass1) {
    super(myclass1);
  }

คำตอบ #2

Angular ไม่อนุญาตให้ การสืบทอดหลายชั้น คุณสามารถ ขยายได้เพียงคลาสเดียว ใน Angular แม้ว่าคุณสามารถ ใช้งานหลายอินเทอร์เฟซ แต่มีวิธีที่คุณสามารถทำการสืบทอดหลายชั้น (เฉพาะตัวอย่างเช่น say) โดยใช้ TypeScript Mixins

ข้อเสียเพียงอย่างเดียวของ mixins คือคุณจะต้อง กำหนดวิธีการทั้งหมดของคลาสฐานที่ใช้ในคลาสลูก [หมายเหตุ - นี่ไม่ใช่การสืบทอดจริง โดยพื้นฐานแล้ว คุณกำลังเพิ่มคุณสมบัติทั้งหมดของคลาสฐานไปยังคลาสลูก]

นอกจากนี้ คุณจะต้อง ประกาศ เมธอด mixin ที่ใดที่หนึ่งในโค้ดของคุณซึ่งจะทำงานหนักทั้งหมด (โดยปกติควรอยู่ที่ app.module เพื่อให้เข้าถึงได้ทั่วทั้งแอป)

ด้านล่างนี้เป็นวิธี mixin:

function applyMixins(derivedCtor: any, baseCtors: any[]) {
    baseCtors.forEach(baseCtor => {
        Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
             if (name !== 'constructor') {
                 derivedCtor.prototype[name] = baseCtor.prototype[name];
            }
        });
    });
}

เอกสารอ้างอิง - https://www.stevefenton.co.uk/2014/02/TypeScript-Mixins-Part-One/

โปรดดูตัวอย่างโค้ดสำหรับ ChildComponent ของคุณ ฉันได้เพิ่มวิธี mixin ใน ChildComponent ของคุณเองแล้ว คุณสามารถวางมันที่ใดก็ได้ในโค้ดของคุณ

export class ChildComponent  {
  propertyClass1: string;
  propertyComp1:string;
  sayHelloClass: (value) => void;
  init: (value) => void;
  sayHelloComponent: (value) => void;
  constructor(private service: Service1Service) { 
      // super()
  }

  ngOnInit() {
    this.applyMixins(ChildComponent, [MyCom1Component,MyClass1]);
    this.sayHelloClass(this.propertyClass1);
    this.init("hoohoho");
    this.sayHelloClass(this.propertyClass1);
    this.sayHelloComponent(this.propertyComp1);
  }

  applyMixins(derivedCtor: any, baseCtors: any[]) {
    baseCtors.forEach(baseCtor => {
        Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
            if (name !== 'constructor') {
                derivedCtor.prototype[name] = baseCtor.prototype[name];
            }
        });
    }); 
  }
} 

บทความที่เกี่ยวข้อง