Angular 抽象基础上的 9 个装饰器 class

Angular 9 decorators on abstract base class

我正在努力将我的项目从 Angular 8 升级到 9,并且在扩展 classes 时遇到了新要求的问题。

根据Angular的documentation

Undecorated base classes using Angular features

As of version 9, it's deprecated to have an undecorated base class that:

  • uses Angular features
  • is extended by a directive or component

Angular lifecycle hooks or any of the following Angular field decorators are considered Angular features:

  • @Input()
  • @Output()
  • @HostBinding()
  • @HostListener()
  • @ViewChild() / @ViewChildren()
  • @ContentChild() / @ContentChildren()

对于 @Component 装饰器,它需要在基础 class 上使用 templatetemplateURL。添加任何一个都会导致子 class 不呈现它的模板。

例如,以下结果不会在视图上呈现任何内容:

@Component({
  template: ''
})
export abstract class BaseComponent<T extends AbstractSuperEntity> extends Toggler implements OnChanges {
  @Input()
  year: number | string

  constructor(service: MyService) {

  }

  ngOnChanges() {
  }
}

@Component({
  templateUrl: 'my.component.html',
  selector: 'my-component'
})
export class MyComponent extends BaseComponent<AbstractSuperEntity> {

  constructor(service: MyService) {
    super(service);
  }

}

我尝试将基数 class 更改为使用指向空 html 的 templateUrl,但这也不起作用。

您必须添加一个空的 @Directive() 装饰器。据我所知,这应该足够了:

@Directive()
export abstract class BaseComponent<T extends AbstractSuperEntity> extends Toggler implements OnChanges {
  @Input()
  year: number | string

  constructor(service: MyService) {

  }

  ngOnChanges() {
  }
}

问这个问题已经有一段时间了,但我偶然发现了它,所以这可能对其他人也有用。

您不一定要添加@Directive 装饰器。如果它是一个组件,只需使用 @Component 代替。那应该有效。请参阅以下 stackblitz 示例:

https://stackblitz.com/edit/angular-ivy-kehmwu?file=src/app/app.component.ts

问题中的问题不清楚。错误消息会有所帮助。

也可能出错的是 OP 没有在 super 调用上实现生命周期方法:

import { Component, OnInit, Input } from '@angular/core';

@Component({
  template: '',
})
export abstract class BaseComponent implements OnInit {
  @Input()
  year: number | string;

  constructor() {}

  ngOnInit() {
    console.log('This will only work if you call it in the child component');
  }
}

@Component({
  selector: 'child-component',
  template: '<p>test, year: {{ year }}</p>',
})
export class ChildComponent extends BaseComponent implements OnInit {
  constructor() {
    super();
  }

  ngOnInit() {
    super.ngOnInit();
  }
}