Angular 2组件中的继承

fgo*_*lez 0 javascript typescript ecmascript-6 angular

我正在使用ANgular 2在我当前的项目中实现动态表单系统,到目前为止一直很好,但我发现了以下问题:

我有两个代表表单控件的组件,例如:

    @Component({
  selector: 'app-text-area',
  templateUrl: './text-area.component.html',
  styleUrls: ['./text-area.component.css']
})
export class TextAreaComponent implements OnInit {
  label: string;
  formGroup: FormGroup;
  formControlName: string;
  constructor(private injector: Injector) { }

  ngOnInit() {
    this.label = this.injector.get('label');
    this.formGroup = this.injector.get('formGroup');
    this.formControlName = this.injector.get('formControlName');
  }
}
Run Code Online (Sandbox Code Playgroud)

和:

@Component({
  selector: 'app-input-text',
  templateUrl: './input-text.component.html',
  styleUrls: ['./input-text.component.css']
})
export class InputTextComponent  implements OnInit{
  label: string;
  formGroup: FormGroup;
  formControlName: string;
  constructor(private injector: Injector) { }

  ngOnInit() {
    this.label = this.injector.get('label');
    this.formGroup = this.injector.get('formGroup');
    this.formControlName = this.injector.get('formControlName');
  }
}
Run Code Online (Sandbox Code Playgroud)

如你所见,两者都是相同的,除了templateUrl,它显示不同的html元素.

所以我想重构代码并创建一个抽象组件来提供公共属性和逻辑,然后使子类继承基类(就像我在使用Java时那样).所以我创建了这个类:

export class AbstractFormControl implements OnInit {
  label: string;
  formGroup: FormGroup;
  formControlName: string;
  constructor(private injector: Injector) { }

  ngOnInit() {
    this.label = this.injector.get('label');
    this.formGroup = this.injector.get('formGroup');
    this.formControlName = this.injector.get('formControlName');
  }
}
Run Code Online (Sandbox Code Playgroud)

我让子类扩展基类,如下所示:

@Component({
  selector: 'app-input-text',
  templateUrl: './input-text.component.html',
  styleUrls: ['./input-text.component.css']
})
export class InputTextComponent  extends AbstractFormControl{

} 
Run Code Online (Sandbox Code Playgroud)

但是现在我收到以下错误:

Uncaught Error: Can't resolve all parameters for InputTextComponent: (?).
Run Code Online (Sandbox Code Playgroud)

有人可以解释一下,做到这一点的正确方法是什么,或者我做错了什么?

yur*_*zui 5

角度依赖注入系统应该知道哪个类型已经传递给构造函数.当您继承组件时,typescript将不会保留有关参数的信息private injector.您有两种选择:

1)重复初始化

@Component({
  ...
})
export class InputTextComponent  extends AbstractFormControl{
    constructor(injector: Injector) { super(injector);}
}
Run Code Online (Sandbox Code Playgroud)

但是在你的情况下,你的基类和继承类中有相同数量的参数,这个解决方案似乎是多余的,因为我们可以省略派生类中的构造函数.

如果我们只想使用父类的依赖关系,我们可以省略派生类中的构造函数.所以我们假设我们的父类如下:

abstract class Parent {
  constructor(private a: string, private b: number) {}
}
Run Code Online (Sandbox Code Playgroud)

我们也可以扩展这个类

class Foo extends Parent {
  constructor(a: string, b: number) {
    super(a, b);
  }
}
Run Code Online (Sandbox Code Playgroud)

要么

class Foo extends Parent {
}
Run Code Online (Sandbox Code Playgroud)

因为第二个选项会生成代码

function Foo() {
   return _super !== null && _super.apply(this, arguments) || this;
}
Run Code Online (Sandbox Code Playgroud)

Plunker示例

2)@Injectable用于基类.

@Injectable()
export class AbstractFormControl {
Run Code Online (Sandbox Code Playgroud)

这种方式打字稿会将上面的代码翻译成

AbstractFormControl = __decorate([
    core_1.Injectable(),
    __metadata("design:paramtypes", [core_1.Injector])
], AbstractFormControl);
Run Code Online (Sandbox Code Playgroud)

Plunker示例

和角度反射器可以轻松读取此信息

3)@Inject()用于每个参数

export class AbstractFormControl implements OnInit {
  constructor(@Inject(Injector) private injector: Injector) { }
Run Code Online (Sandbox Code Playgroud)