Angular:使用基于路由的动态InjectionTokens?

问题描述 投票:1回答:1

我想知道如何初始化一个依赖于另一个服务的服务和一个用于实例化服务中的依赖项的复杂对象。目前,我使用InjectionToken将复杂对象推送到服务中,但我需要动态地将不同的复杂对象推送到服务,具体取决于用户所采用的路由。

为了演示这个问题,假设我有一个依赖于HelperService的InterestingService和一个包含用于实例化内部服务类的参数的对象:

InterestingService

...
@Injectable()
export class InterestingService {

  interestingObject: InterestingObject;

  constructor(private helperService: HelperService,
              @Inject(PARMS) private parms: ParmsTemplate) {
    // parms e.g. {value1: 'aaa', value2: [1,2,3]}
    this.interestingObject = new InterestingObject(parms);
  }

  doSomething() {
    this.interestingObject.doSomethingAwesome()
  }
}

参数必须遵循特定格式:

ParmsTemplate

export interface ParmsTemplate {
  value1?: string,
  value2: number[]
}

该服务由组件使用:

SomeComponent

import { Component, OnInit } from '@angular/core';
import { InterestingService } from './interesting.service';

@Component({
  selector: 'app-some-component',
  templateUrl: './some.component.html',
  styleUrls: ['./some.component.css']
})
export class SomeComponent implements OnInit {

  constructor(public service: InterestingService) { }

  ngOnInit() {
    this.service.doSomething();
  }
}

PARMS中包含InjectorToken定义以及一组预定义的配方:

PARMS and canned RECIPES

import { Injectable } from '@angular/core';
import { InjectionToken } from '@angular/core';
import { ParmsTemplate } from './parms';

export const PARMS = new InjectionToken<ParmsTemplate> ('parms.for.interesting.objects');

export const RECIPE_1: ParmsTemplate = {
  value1: 'aaa',
  value2: [1,2,3]
}

export const RECIPE_2: ParmsTemplate = {
  value1: 'bbb',
  value2: [1,2,3,4,5,6,7]
}

export const RECIPE_3: ParmsTemplate = {
  value2: [1,2]
}

InjectionToken在AppModule中初始化:

AppModule

...
import { RECIPE_1, RECIPE_2, RECIPE_3, PARMS } from './parms';
import { InterestingService } from './interesting.service';
import { HelperService } from './helper.service';

@NgModule({
  declarations: [
    SomeComponent
  ],

  imports: [
    BrowserModule,
    FormsModule,
    AppRoutingModule,
    HttpClientModule
  ],
  exports: [ ],
  providers: [
    InterestingService, 
    HelperService,
    {
      provide: PARMS, useValue: RECIPE_1
    }
  ],
  entryComponents: [ ],
  bootstrap: [AppComponent]
})
export class AppModule { }

最后,定义了路线:

AppRoutingModule

...
import { NgModule }             from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { SomeComponent }     from './some.component';

const routes: Routes = [
  { path: 'recipe1', component: SomeComponent },
  { path: '', redirectTo: '/', pathMatch: 'full' },
  { path: '**', redirectTo: '/'}
];

@NgModule({
  imports: [ RouterModule.forRoot(routes) ],
  exports: [ RouterModule ]
})
export class AppRoutingModule {}

这一切都很好,而且适用于一个食谱。我想做的是扩展我的路线以包括其他食谱:

...
const routes: Routes = [
  { path: 'recipe1', component: SomeComponent },
  { path: 'recipe2', component: SomeComponent },
  { path: 'recipe3', component: SomeComponent },
  { path: '', redirectTo: '/', pathMatch: 'full' },
  { path: '**', redirectTo: '/'}
];
...

问题是我的InjectionToken只能在AppModule中设置为一个值。

  1. 有没有办法可以根据路由指定要使用哪个InjectionToken?
  2. 是否有一种不同的方法可以用来保持InjectionToken策略但是将不同的配方参数推送到我的共享服务中?
  3. 你认为这对工厂提供商来说是一个更好的工作吗?如果是这样,你会如何建议我使用工厂提供商来使用我的不同配方并为相关路线提供服务(例如/ recipe2带您到SomeComponent,InterestingService使用来自RECIPE_2的parms初始化InterestingObject)?
  4. 那么使用路线数据呢?如果是这样,您如何将路线数据注入服务? (实际上,这很容易,可能是最好的解决方案:将Route注入InterestingService,将配方作为其特定路由的路由数据传递,并使用route.data()获取服务中的配方数据。)
angular service dependency-injection routing
1个回答
0
投票

最后,我重构了我的代码,以消除对基于路由的数据的需求,而是创建了一个服务来保存预制的配方并初始化InterestingObject。我对这个解决方案感到非常高兴。

在此之前,我能够使用路由数据,但我不得不使用ActiveRoute和不同的路由事件来获取组件中的数据。虽然这很有效,但它影响了我创建动态配方和重用组件的能力,因为尝试将数据推送到路径中是很尴尬的。该服务显然是正确的答案。

我将我的罐装食谱设置为共享服务的方法。不幸的是,我不得不将它们设置为实例方法,以便HTML中的表达式可以引用它们。我尝试将它们设为静态变量,但表达式似乎无法在服务上看到静态,但是它们可以看到实例引用没有问题。

© www.soinside.com 2019 - 2024. All rights reserved.