Angular如何根据@Input输入值动态切换组件providers的useClass实现
问题原因说明
Angular组件的@Component.providers配置是在组件实例化前就解析完成的,此时@Input属性还没有被赋值,因此无法直接在providers配置中根据Input值动态选择实现类。同时注入的服务默认是独立于组件实例的,没有直接访问组件Input属性的权限。
可行解决方案
方案1:通过setter向服务传递Input值(改动最小,推荐)
把判断逻辑保留在工具类中,通过组件@Input的setter同步输入值给服务,支持输入值后续动态变更的场景:
- 给工具类新增可赋值的date属性
@Injectable() export class MyCalendarUtils extends CalendarUtils { date: 'today' | 'events' = 'today'; getMonthView(args: GetMonthViewArgs): MonthView { console.log(args); if (this.date === 'today') { args.viewStart = subWeeks(startOfMonth(args.viewDate), 0); args.viewEnd = addWeeks(endOfMonth(args.viewDate), 1); } else { const length = args.events.length; args.viewStart = subWeeks(startOfMonth(args.events[0].start), 0); args.viewEnd = addWeeks(endOfMonth(args.events[length - 1].start), -2); } return super.getMonthView(args); } }
- 组件中同步Input值到服务
@Component({ selector: 'app-match-calendar', templateUrl: './match-calendar.component.html', styleUrls: ['./match-calendar.component.scss'], providers: [ { provide: CalendarUtils, useClass: MyCalendarUtils, }, { provide: DateAdapter, useFactory: adapterFactory, } ], }) export class MatchCalendarComponent implements OnInit, OnDestroy { constructor(@Inject(CalendarUtils) private calendarUtils: MyCalendarUtils) {} @Input() set date(val: 'today' | 'events') { this.calendarUtils.date = val; } get date() { return this.calendarUtils.date; } }
方案2:useFactory动态选择实现类(适合逻辑拆分要求高的场景)
如果需要保留两个独立的实现类,可利用组件级provider工厂可以注入当前组件实例的特性实现动态选择,仅适用于输入值初始化后不会变更的场景:
@Component({ selector: 'app-match-calendar', templateUrl: './match-calendar.component.html', styleUrls: ['./match-calendar.component.scss'], providers: [ // 注册两个实现类为可注入对象 MyCalendarUtils, EventsView, { provide: CalendarUtils, useFactory: (component: MatchCalendarComponent, todayUtil: MyCalendarUtils, eventUtil: EventsView) => { return component.date === 'today' ? todayUtil : eventUtil; }, // 声明工厂依赖 deps: [MatchCalendarComponent, MyCalendarUtils, EventsView] }, { provide: DateAdapter, useFactory: adapterFactory, } ], }) export class MatchCalendarComponent implements OnInit, OnDestroy { // 必须给默认值,避免工厂解析时输入值为undefined @Input() date: 'today' | 'events' = 'today'; }
内容的提问来源于stack exchange,提问作者jexists
相关产品推荐
相关产品推荐

