Angular组件TypeScript代码重构:如何避免各保障线代码重复?
重构Angular组件代码以消除重复
嘿,这段代码的重复问题确实很明显——不管是医疗、牙科还是视力保障的视图生成逻辑,几乎都是一模一样的。我们可以通过提取复用函数和配置化处理这两个步骤,彻底干掉这些重复代码,同时还能让后续维护更轻松。
第一步:把重复的视图转换逻辑抽成单独函数
首先,你会发现所有XXXBenefitsGroupsView的生成逻辑都是map+sort的组合,只是输入的过滤后分组不同而已。我们把这部分逻辑抽成一个私有函数,以后不管哪个保障线都用它来生成视图:
// 假设你已经定义了BenefitGroup(原始数据类型)和BenefitsGroupView(视图类型) private createBenefitsGroupsView(groups: BenefitGroup[]): BenefitsGroupView[] { return groups.map((group) => ({ value: group.benefitGroupId, viewValue: group.benefitGroupName, checked: group.benefits.every(b => b.isDisplayable), // 如果通用视图需要保留coverageLineId就留着,不需要可以删掉 coverageLineId: group.benefits[0].coverageLineBenefits[0].coverageLineId, benefits: group.benefits .sort((a, b) => a.benefitName.localeCompare(b.benefitName)) .map((b) => ({ value: b.benefitId, viewValue: b.benefitName, checked: b.isDisplayable, groupValue: group.benefitGroupId, })), })); }
第二步:用配置化方式批量处理各保障线的过滤和视图生成
接下来,我们把不同保障线的coverageLineId和对应的视图属性名做成一个配置数组,然后循环处理每个配置,这样新增保障线的时候只需要加一行配置就行,不用重复写过滤和映射代码:
// 先处理基础的无过滤视图 const filteredBaseGroups = benefitGroups .filter((x) => x.benefits.length) .sort((a, b) => a.benefitGroupName.localeCompare(b.benefitGroupName)); this.benefitsGroupsView = this.createBenefitsGroupsView(filteredBaseGroups); // 定义各保障线的配置:属性名 + 对应的coverageLineId const coverageLineConfigs = [ { propName: 'medicalBenefitsGroupsView', coverageLineId: 1 }, { propName: 'dentalBenefitsGroupsView', coverageLineId: 2 }, { propName: 'visionBenefitsGroupsView', coverageLineId: 3 }, ]; // 循环生成每个保障线的视图 coverageLineConfigs.forEach((config) => { // 按当前配置的coverageLineId过滤分组 const filteredGroups = filteredBaseGroups.filter((group) => { return group.benefits.some((benefit) => benefit.coverageLineBenefits.some(b => b.coverageLineId === config.coverageLineId) ); }); // 调用复用函数生成视图并赋值到组件属性 (this as any)[config.propName] = this.createBenefitsGroupsView(filteredGroups); });
额外福利:统一模板中的ngFor
现在你还可以进一步简化模板——不用写三个重复的*ngFor,而是在组件里加一个activeBenefitsView变量,根据上下文切换它的值:
// 组件里定义一个变量用来控制当前显示的视图 activeBenefitsView: BenefitsGroupView[]; // 比如在切换到医疗保障时: this.activeBenefitsView = this.medicalBenefitsGroupsView; // 切换到牙科时: this.activeBenefitsView = this.dentalBenefitsGroupsView; // 切换到视力时: this.activeBenefitsView = this.visionBenefitsGroupsView;
然后模板里只需要写一行:
<div *ngFor="let benefitGroup of activeBenefitsView;"> </div>
这样模板也变得简洁多了!
小细节优化
- 如果你觉得
(this as any)不够类型安全,可以给组件定义一个接口,明确这些视图属性的类型,或者把所有视图存在一个对象里(比如this.benefitsViews = {}),这样类型检查更友好。 - 可以给
group.benefits[0].coverageLineBenefits[0].coverageLineId加上可选链?.,避免极端情况下出现报错(不过之前已经过滤了x.benefits.length,所以其实不会有问题,但加上更稳妥)。
内容的提问来源于stack exchange,提问作者noclist
相关产品推荐
相关产品推荐

