如何利用Angular Signals实现组件可见性切换?
如何用Angular Signals重构组件显隐控制代码
问题背景
我了解Angular Signals可用于当前场景以避免频繁调用isVisible函数,但对该新特性缺乏经验,不清楚需要修改代码中的哪些部分来运用它。以下是我简化后的原有代码片段:
原有TS代码
visibleSections = []; sectionConfig = [ { name: 'someComponent', hidden: false }, { name: 'otherComponent', hidden: false } ]; ngOnInit() { this.visibleSections = this.sectionConfig.filter(c => !c.hidden); } public isVisible(section): boolean { return this.visibleSections.findIndex(s => s.name === section) > -1; } public setSectionVisibility(e: any): void { this.sectionConfig.find(c => c.name === e.itemValue.name).hidden = e.value.findIndex(p => p === e.itemValue) === -1; }
原有HTML代码
<p-multiSelect #multiselect defaultLabel="Show/hide sections" optionLabel="title" name="show-hide-sections" scrollHeight="300px" styleClass="multiselect-as-button mr-3 ml-3" dropdownIcon="fas fa-bars rotate-90" [options]="sectionConfig" [(ngModel)]="visibleSections" [displaySelectedLabel]="false" (onChange)="setSectionVisibility($event)" [style]="{ width: '208px' }" [showHeader]="false" [appendTo]="'body'"></p-multiSelect> @if (isVisible("someComponent")) { <some-component></some-component> } @if (isVisible("otherComponent")) { <other-component></other-component> }
适配Angular Signals的实现(Angular 18版本)
结合参考方案,考虑到Angular 18暂不支持linkedSignal,最终实现方式如下:
修改后的TS代码
type Config = { name: string; hidden: boolean; }; sectionConfig = signal<Config[]>([ { name: 'someComponent', hidden: false, }, { name: 'otherComponent', hidden: false }]); visibleSections = computed(() => { const sections = this.sectionConfig(); return sections.filter(s => !s.hidden); }); public visibleSectionsFlags = computed(() => { return this.sectionConfig() .filter(item => !item.hidden) .map(item => item.name); }); public setSectionVisibility(e: any): void { this.sectionConfig.update(currentConfig => { const foundIndex = currentConfig.findIndex(c => c.name === e.itemValue.name); if (foundIndex > -1) { // 不可直接修改原数组元素,需返回新数组触发信号更新 const updatedConfig = [...currentConfig]; updatedConfig[foundIndex].hidden = !updatedConfig[foundIndex].hidden; return updatedConfig; } return currentConfig; }); }
修改后的HTML代码
<p-multiSelect #multiselect defaultLabel="Show/hide sections" optionLabel="title" name="show-hide-sections" scrollHeight="300px" styleClass="multiselect-as-button mr-3 ml-3" dropdownIcon="fas fa-bars rotate-90" [options]="sectionConfig()" [ngModel]="visibleSections()" [displaySelectedLabel]="false" (onChange)="setSectionVisibility($event)" [style]="{ width: '208px' }" [showHeader]="false" [appendTo]="'body'"></p-multiSelect> @if (visibleSectionsFlags().includes("someComponent")) { <app-some-component></app-some-component> } @if (visibleSectionsFlags().includes("otherComponent")) { <app-other-component></app-other-component> }
关键修改点说明
- 将原有的普通数组
sectionConfig改为Signal数组,用signal()创建,确保数据变化能被Angular追踪 - 用
computed()创建派生信号visibleSections和visibleSectionsFlags,自动依赖sectionConfig的变化更新,替代原有的ngOnInit初始化和isVisible函数 - 更新
setSectionVisibility方法:使用signal.update()修改数据,必须返回新数组(不可直接修改原数组元素),才能触发信号的变化通知 - HTML中绑定Signal值时需加上
(),比如sectionConfig()、visibleSections(),获取信号的当前值 - 组件显隐判断直接使用
visibleSectionsFlags()的数组包含判断,替代原有的isVisible函数调用
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

