angular - 避免在 init 之后评估 Angular 指令的输入属性

我有一个非常简单的 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。因此,我想在初始化时阅读 value 一次,但之后忽略它。我知道 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,但类似的东西可能会很好。

回答1

我想这不是在指令定义方面要解决的问题。每次更改检测在托管该 div 的组件上运行时,都会对字符串 getter 进行昂贵的计算。因此,我不会在模板中使用那个昂贵的字符串 getter,而是会设法将该结果分配给我的类中的一个变量并在模板上使用该变量。您可以在托管该 div 的组件中对 ngOnInit 或其他更适合您的条件的生命周期挂钩进行昂贵的计算。

只是为了澄清,这是我正在谈论的 div:

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

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

相似文章