如何优化计算信号:防止在更改检测后重新创建每个项目?

问题描述 投票:0回答:1

我正在使用 Angular 19 和新的信号 API(以及 OnPush 策略)。我有一个组件将当前 URL 作为信号进行跟踪,然后对于数组中的每个项目(例如菜单),我创建一个计算信号来检查它是否与 URL 匹配。这是一个简化版本:

export class MenuComponent {
  url = toSignal(
    this.router.events.pipe(
      filter(e => e instanceof NavigationEnd),
      map(e => e.urlAfterRedirects)
    )
  );

  isActivated(item: MenuItem) {
    return computed(() => this.url()?.startsWith(item.routerLink) ?? false);
  }

  // Template snippet:
  // <li *ngFor="let item of items">
  //   <a [routerLink]="item.routerLink" [class.active]="isActivated(item)()">
  //     {{ item.label }}
  //   </a>
  // </li>
}

问题: 每次检查模板时,它都会调用 isActivated(item),这会为每个项目创建一个新的计算信号实例。我怀疑有一种更有效的方法可以做到这一点。推荐的模式或方法是什么,可以避免每次都为每个项目创建新的计算,同时仍然保持应用程序对 URL 更改做出反应?

angular angular-changedetection angular-signals
1个回答
0
投票

您应该首先将项目转换为信号。

items = signal([]);

创建一个计算信号,它将对

url
信号和
items
信号的变化做出反应,这个计算信号可以在 for 循环中使用来直接添加
active
类。

itemsComputed = computed(() => {
  const url = this.url();
  return this.items().forEach((item: any) => {
    item.active = item.routerLink.includes(url);
    return item;
  });
});

最后,我们可以运行一个 for 循环并使用这个

active
属性。

@for(let item of items; track $index) {
  <li>
    <a [routerLink]="item.routerLink" [class.active]="item.active">
      {{ item.label }}
    </a>
  </li>
}
© www.soinside.com 2019 - 2024. All rights reserved.