Angular如何将组件内重复方法抽离为独立函数且不创建service
实现方案
你可以直接把公共逻辑抽离为独立的工具函数,放在单独的utils文件中,以下是两种可行的实现方式:
方案1:显式传递所有依赖(推荐,类型安全、耦合度低)
将方法中用到的所有组件属性、服务、回调方法都作为参数传入工具函数,不需要依赖组件实例。
第一步:编写工具函数(如src/utils/device.utils.ts)
import { NewBuildingStatisticsService } from '你的服务实际路径'; import { Subscription } from 'rxjs'; // 可根据实际业务替换以下any为具体类型 export function compareWithMainDevice( statisticsService: NewBuildingStatisticsService, isDetail: boolean, onSetMainId: (id: string | number) => void, getDeviceList: () => any[], onSetDeviceList: (list: any[]) => void, updateChart: (flag: boolean) => void ): Subscription { return statisticsService.getMainDeviceAggregates(isDetail).subscribe(mainDeviceAggregates => { onSetMainId(mainDeviceAggregates.device_id); const mainDev = JSON.parse(JSON.stringify(mainDeviceAggregates)); const otherDevs = getDeviceList(); const tempList = [mainDev, ...otherDevs]; const calculateDev = tempList.reduce((prev, curr) => { curr.cost.forEach(({ value }, index) => { if (mainDev.cost.length > index && prev.cost[index].value > curr.cost[index].value) { prev.cost[index].value -= value; } }); return prev; }); onSetDeviceList([...otherDevs, calculateDev]); updateChart(true); }); }
第二步:组件内调用
// 顶部导入工具函数 import { compareWithMainDevice } from 'src/utils/device.utils'; // 原方法替换为调用工具函数 private compareWithMainDevice(): void { // 订阅需存在组件实例中,组件销毁时统一取消订阅避免内存泄漏 this.compareSub = compareWithMainDevice( this.newBuildingStatisticsService, this.isDetail, (id) => this.mainDeviceId = id, () => this.deviceAggregates, (list) => this.deviceAggregates = list, (flag) => this.setChartOption(flag) ); }
方案2:传递组件上下文(写法更简洁)
通过接口约束组件必须具备的属性和方法,直接把组件实例this传入工具函数。
第一步:编写工具函数
import { NewBuildingStatisticsService } from '你的服务实际路径'; import { Subscription } from 'rxjs'; // 约束传入的组件必须具备以下属性/方法 interface ICompareComponent { newBuildingStatisticsService: NewBuildingStatisticsService; isDetail: boolean; mainDeviceId: string | number; deviceAggregates: any[]; setChartOption: (flag: boolean) => void; } export function compareWithMainDevice(component: ICompareComponent): Subscription { return component.newBuildingStatisticsService.getMainDeviceAggregates(component.isDetail).subscribe(mainDeviceAggregates => { component.mainDeviceId = mainDeviceAggregates.device_id; const mainDev = JSON.parse(JSON.stringify(mainDeviceAggregates)); const otherDevs = component.deviceAggregates; const tempList = [mainDev, ...otherDevs]; const calculateDev = tempList.reduce((prev, curr) => { curr.cost.forEach(({ value }, index) => { if (mainDev.cost.length > index && prev.cost[index].value > curr.cost[index].value) { prev.cost[index].value -= value; } }); return prev; }); component.deviceAggregates = [...otherDevs, calculateDev]; component.setChartOption(true); }); }
第二步:组件内调用
// 顶部导入工具函数 import { compareWithMainDevice } from 'src/utils/device.utils'; private compareWithMainDevice(): void { this.compareSub = compareWithMainDevice(this); }
注意事项
- 两种方案返回的RxJS订阅都需要在组件
ngOnDestroy生命周期中调用unsubscribe销毁,避免内存泄漏 - 方案一不依赖组件具体实现,适配性更高;方案二写法更简洁,适合内部业务场景复用
- 可根据实际业务类型定义,替换代码中的
any为具体类型,提高TypeScript类型安全性
内容的提问来源于stack exchange,提问作者shadiq
相关产品推荐
相关产品推荐

