我正在使用 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 更改做出反应?
您应该首先将项目转换为信号。
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>
}