Angular 9 为服务做抽象类 需要@injectable 装饰器?

Angular 9 do abstract classes for services need the @injectable decorator?

升级到 Angular 9 后,我的一些服务扩展的摘要 类 会自动用 @injectable 装饰,如 Angular 9 迁移指南中所写。

我的应用程序上的一切正常。

但是我不明白为什么抽象 类 必须被装饰,因为扩展它们的具体 类 确实有 @injectable 装饰器。

我也阅读了这个问题 ,建议从摘要中删除 @injectable

所以我应该删除装饰器吗?

这只是一个 Angular "mistake" 用于将装饰器添加到我的摘要中吗?

此外,我注意到 @directive 装饰器已添加到用于实现组件的其他抽象 类。

直到 Angular 8 个装饰器对于指令和组件的基础 类 是可选的。使用最新 angular 版本 (9)。 类 需要装饰器。

For More Details

Link2

要添加一些附加信息:

Ivy 中的一个关键概念是局部性,因此为了编译或重新编译组件,编译器不再扫描整个代码库 - 仅重新编译组件;并且,组件的所有行为都必须在已编译的 class 中捕获。 The link provided in other answers provides more details on the "why".

基础 classes(抽象或非抽象)具有 Angular 装饰器(@Directive@Component@Injectable, @NgModule) 仅在基础 classes 使用 Angular 功能时适用,例如,如果它们实现生命周期接口,如 OnInitOnDestroy。如果您的基础 classes 不使用 Angular 功能,则您不需要 Angular 装饰器。

在Angular9中,这个要求是可选的;但不要从 CLI 升级放置在那里的基础 classes 中删除装饰器,因为此要求在 Angular 10.

中是非可选的

这里有一些关于此的附加信息:

  • 我们知道 Ivy 对 class 装饰器等的要求

但是,这是我刚刚经历的一个序列,这似乎意味着没有办法为指令创建抽象基础 class,如果 class 使用 angular特征(输入等)。需要重构。

  • 有一个组件使用了一个基 class。它是抽象的并且使用 angular 特征。
  • 升级了,看到添加了空指令。
  • 无法编译。指令中需要元数据对象。
  • 查看文档 (Angular.io),说要用空白选择器添加数据。

我做了所有这些,即使 TS lint 抱怨空白选择器,我用 tslint:disable...

关闭了它

...虽然不再显示为 lint 错误,但现在显示为构建错误(实际上是说,“请添加它!”)。所以我添加了一个带有一些永远不会被使用的概念的选择器,因为 class 是抽象的。

但是...

...class 以前没有添加到模块中。我没有编写原始代码,并且很惊讶这从来没有出现在 --prod 构建中,但是阅读有关以前的图形引擎的信息,我发现它是宽容的,因为它具有全局可见性。但是 Ivy 没有,它是独立编译的,所以你需要我放置的装饰器,no-module 错误就出现了。所以我把它添加到相关模块中。

...没有利润。 “不能将抽象构造函数添加到非抽象构造函数。”换句话说,我猜,你不能在模块中声明一个抽象 class(至少,不是通常的“将它添加到声明中”的方式)。

所以最终,由于没有考虑重构相当复杂的组件层次结构,我只是从 class 定义中删除了抽象。

然而,这个序列确实邀请了直接并通过其选择器使用该碱基 class 的机会。这不是框架强迫你进入的好状态。

我摆弄了一下,但找不到直接绕过它的方法。

所以在这里扩展答案:

“如果抽象 classes 使用 angular 功能,你似乎不能使用它们,因为如果你使用这些功能,你必须在 class,表示必须在模块中声明,禁止声明abstract classes."

(即使文档说“你可以将选择器留空”,除非你想调整你的规则,但似乎你不能)。

您的问题与 Undecorated Parent 模式有关。

我不能在没有看到的情况下对您的代码进行具体评论,但作为一般观点,使用聚合而不是继承 可能更好。换句话说,将您的基础 class 重新设计为一项服务,然后将其注入派生的 class.