避免在初始化后评估 Angular 指令的输入属性

Avoid evaluating input properties on Angular directives after init

我有一个非常简单的 Angular 属性指令,看起来像这样:

import { Directive, Input, OnInit } from "@angular/core";

@Directive({
  selector: "[foo]",
})
export class FooDirective implements OnInit {
  @Input() public foo: string;

  public ngOnInit(): void {
    // Do something here once
  }
}

会这样使用:

<div [foo]="bar"></div>

bar 可能是一个简单的字符串,但也可能是一个比 运行 相对昂贵的字符串 getter。 因此,我想在初始化时读取一次值,但之后忽略它。 我知道 ngOnInit 只被调用一次,但是更改检测会导致 bar 属性 被重复调用(取决于包含组件的工作方式)。

使用 @Attributes 会更好,因为它们只被评估一次。 但是 @Attribute 似乎不适用于指令(同名?):

import { Directive, OnInit, Attribute } from "@angular/core";

@Directive({
  selector: "[foo]",
})
export class FooDirective implements OnInit {
  public constructor(
    @Attribute("foo")
    private readonly foo: string
  ) {}

  public ngOnInit(): void {
    // Do something with this.foo here
  }
}

如何避免多次计算输入 属性? 我宁愿退订任何更改,可以这么说。

指令似乎不支持 ChangeDetectionStrategy.OnPush,但类似的东西可能会更好。

我想这不是指令定义方面要解决的问题。每次更改检测在托管 div 的组件上运行时,都会对字符串 getter 进行昂贵的计算。 因此,我不会在模板中使用昂贵的字符串 getter,而是将结果分配给 class 中的一个变量,然后在模板中使用该变量。您可以在托管 div.

的组件中对 ngOnInit 或其他更适合您的条件的生命周期挂钩进行昂贵的计算

澄清一下,这就是我所说的 div:

  <div [foo]="bar"></div>

为了快速总结,我的建议是在托管此 div 的组件中使用生命周期挂钩来获取值,传递给变量,并在模板上使用该变量而不是昂贵的字符串 getter.