用不同的构造函数继承两个有角度的组件

时间:2019-05-07 03:04:31

标签: angular typescript

这与在打字稿中扩展2类有点类似,但是尽管我设法在打字稿中做到了这一点,但我找不到在angular中正确的方法。

我有一个带有1个组件,一个服务和一个通用类的angular 7应用。

就像这样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
}

}

编译器没有给出错误,但我的组件方法未继承

4 个答案:

答案 0 :(得分:4)

我建议采用另一种方法。 通过用@Injectable

注释使类对DI可用

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

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

答案 1 :(得分:2)

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

带有downside的唯一mixins是您将必须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的代码段。我已经在您的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];
            }
        });
    }); 
  }
} 

答案 2 :(得分:1)

您可以使用 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);
        }
  };
};

在简历中,您使用此方法所要做的是在各个mixins中分离类逻辑,例如:

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示例,因为在此发布的代码中缺少一些正确实现所需的样板和类型。

希望这可以有所帮助!

答案 3 :(得分:0)

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

您应该寻找重用代码的另一种方式,就像Jose Guzman刚才说的那样。 也许创建服务