【问题标题】:inherit two component in angular with different constructor使用不同的构造函数继承两个组件
【发布时间】:2019-09-24 15:58:24
【问题描述】:

这有点类似于在 typescript 中扩展 2 类,但是虽然我设法在 typescript 中做到了,但我在 angular 中找不到正确的方法。

我有一个 Angular 7 应用程序,其中包含 1 个组件、一个服务和一个通用类。

就是这样Stackblitz

我想创建一个从我的类和我的其他组件继承的组件

这是我的 class=>

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
}

}

编译器没有报错,但是我的组件方法没有被继承

【问题讨论】:

  • 我想知道您这样做的目的是什么?因为另一种方法是创建 2 个不同的父类并在子组件中实例化它们。
  • 基本上,我讨厌重复的代码,这里有一个类似于我为什么要这样做的解释:prntscr.com/nlcxnd希望你能理解。 serviceForAnimal 共享给所有 Animal,serviceForWolf 共享给所有狼。
  • 答案here 可能会对您有所帮助。
  • 我设法只使用打字稿来做到这一点,我正在尝试找到一种使用角度组件和默认类的方法
  • 我只是想提醒一下,多重继承会带来太多的代码复杂性,因为您已经知道还有其他不违反 DRY 的方式。

标签: angular typescript


【解决方案1】:

我会建议一种不同的方法。 通过使用 @Injectable 注释使类对 DI 可用

然后像往常一样扩展您的父组件:ChildComponent extend MyCom1Component 并使用ChildComponent 的构造函数注入您的MyClass1 最后用刚刚注入的类的实例调用父类的构造函数。

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

【讨论】:

    【解决方案2】:

    Angular 不允许Multiple Inheritance。你可以extend only one class 角度,虽然你可以implement multiple interfaces。但是有一种方法可以使用TypeScript Mixins 进行多重继承(only in say)

    唯一的downsidemixins 是你必须define all the used base class methods in the child class。 [注意 - 这不是实际的继承。基本上,您将所有基类属性添加到子类。 ]

    此外,您必须在代码中的某处使用declare mixin 方法,这将完成所有繁重的工作。 (Preferrably the app.module to have global access)

    PFB 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/

    PFB 为您的ChildComponent 提供 sn-p。我在您的ChildComponent 本身中添加了mixin 方法。您可以在代码中的任何位置放置相同的内容。

    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];
                }
            });
        }); 
      }
    } 
    

    【讨论】:

      【解决方案3】:

      您可以使用 Typescript mixins 来实现。 Angular Material 是在它的项目中实现的,你可以查看它的源代码code

      但这种方法远非完美,因为它为您可能不需要的代码添加了许多样板复杂性因此,如果您能避免这种情况,那就更好了

      也就是说,我已经分叉了您的 stackblitz 项目,添加了提到的这个解决方案。

      在您的代码中,您还尝试使用 Typescript mixins,但您从未扩展 MyCom1Component 类,似乎是这样,但在下面的代码中, MyCom1Component 充当变量名! 不是类!

      const addMyClassOneInheritance = <T extends new(...args: any[]) => any>(MyCom1Component: T) => {
        return class extends MyCom1Component /* THIS IS A VARIABLE NAME */ {
              constructor(...args: any[]) {
                  super(...args);
              }
        };
      };
      

      在简历中,您必须使用这种方法在各自的 mixin 中分离类逻辑,例如:

      export function mixinMyCom1Component<T extends Constructor<{}>>(base: T): MyCom1ComponentCtor & T {
        return class extends base {
          propertyComp1 = "MyCom1";
          constructor(...args: any[]) { super(...args); }
          sayHelloComponent(value:string){console.log('component say'+ value)}
        };
      }
      
      export function mixinMyClass1<T extends Constructor<{}>>(base: T): MyClass1Ctor & T {
        return class extends base {
            propertyClass1 = "MyClass1"
            constructor(...args: any[]) { super(...args); }
            init(value:string){
              this.propertyClass1 = value;
            }
            sayHelloClass(value:string){console.log('class say'+ value)}
          };
      }
      

      之后,您可以像这样编写 ChildComponent:

      export class ChildComponentBase {
        constructor() {}
      }
      
      export const _ChildComponentMixinBase = mixinMyClass1(mixinMyCom1Component(ChildComponentBase));
      
      @Component({...})
      export class ChildComponent extends _ChildComponentMixinBase {
          constructor(private service: Service1Service) { 
              super()
          }
      }
      

      PD:请参阅 stackblitz 示例,因为在此发布的代码中缺少一些样板文件和正确实现它所需的类型。

      希望这能有所帮助!

      【讨论】:

        【解决方案4】:

        这在 Angular 中是不可能的,因为在 Javascript 中你不能在一个类中扩展 2 个类,而且一个组件就是一个类。

        正如 Jose Guzman 刚才所说,您应该寻找另一种重用代码的方法。 也许创建服务

        【讨论】:

          猜你喜欢
          • 2015-10-15
          • 1970-01-01
          • 2013-06-01
          • 2023-04-03
          • 2015-06-21
          • 1970-01-01
          相关资源
          最近更新 更多