【发布时间】:2017-07-23 21:22:50
【问题描述】:
我现在正在处理一个非常大的项目,我们正在努力使我们的代码尽可能模块化。我们有多个 Angular 应用程序,我们创建了一个单独的通用 UI 组件库和一个 API 工具包,其中包含跨这些应用程序使用的通用服务。
我们在尝试构建需要与服务一起使用的通用组件时遇到了问题。例如,我现在正在开发一个自动完成组件。该组件应该能够从远程源获取数据并根据输入到组件的输入字段中的内容过滤结果。
对于一个实例来说,这种实现很容易。我在自动完成组件的构造函数中注入自动完成服务,然后在父级上提供它。这使我可以在使用服务时灵活地更改服务的实现细节,同时仍然能够创建一个可与定义的接口一起使用的可重用组件。
例如:
我们要定义自动完成组件使用的接口的服务:
@Injectable()
export class AutocompleteService {
public url: string = 'my-api-default';
constructor(http: Http) {}
fetch(): any {
return this.http.get(this.url);
}
}
自动完成组件实现:
@Component({
selector: 'my-autocomplete',
templateUrl: 'my-autocomplete.component.html'
})
export class MyAutocompleteComponent {
constructor(private autocompleteService: AutocompleteService) {}
getData() {
return this.autocompleteService.fetch();
}
...autocomplete logic...
}
现在我可以定义一个实现自动完成服务的熊服务。我可以将熊服务连接到我的自动完成组件,这样我就可以在我的表单中选择熊的种类。
@Injectable()
export class BearService {
public url: string = 'bear-url';
constructor(http: Http){}
fetch() {
return this.http.get(this.url);
}
}
接下来,我定义了使用我的自动完成组件并提供熊服务来获取我的熊种类数据的父级。
@Component({
selector: 'my-form-component',
template: `
<form>
<my-autocomplete [(ngModel)]="bear"></my-autocomplete>
<button type="submit">Submit</button>
</form>
`,
providers: [
{provide: AutocompleteService, useClass: BearService}
]
})
export class MyFormComponent {
...component logic...
}
到目前为止,一切都很好。
当我需要构建一个使用多个自动完成组件的大型表单时,我的问题就出现了。我的老板告诉我,我需要在此表单上填写三个自动填充字段,一个用于熊类,一个用于甜菜类,一个用于太空堡垒卡拉狄加角色。我的第一个想法是这样做:
我定义了服务实例:
@Injectable()
export class BeetsService {
public url: string = 'beets-url';
constructor(http: Http){}
fetch() {
return this.http.get(this.url);
}
}
@Injectable()
export class BattleStarGallacticaService {
public url: string = 'battlestar-gallactica';
constructor(http: Http){}
fetch() {
return this.http.get(this.url);
}
}
然后我更新父模板和提供者:
@Component({
selector: 'my-form-component',
template: `
<form>
<my-autocomplete [(ngModel)]="bear"></my-autocomplete>
<my-autocomplete [(ngModel)]="beet"></my-autocomplete>
<my-autocomplete [(ngModel)]="battleStarGallactica"></my-autocomplete>
<button type="submit">Submit</button>
</form>
`,
providers: [
{provide: AutocompleteService, useClass: BearService},
{provide: AutocompleteService, useClass: BeetService},
{provide: AutocompleteService, useClass: BattlestarGalacticaService},
]
})
export class MyFormComponent {
...component logic...
}
现在我如何判断哪个自动完成组件使用哪个服务?
我知道我现在将始终使用为 AutocompleteService 提供的最后一个提供程序,因为这就是 Angular DI 框架的工作方式。
我也知道我不能在这方面使用多提供者,因为 Angular 只为 NG_VALIDATORS 和 NG_ASYNC_VALIDATORS 定义了它们。
那么,有人知道如何解决我的问题吗?我不在乎如何问题本身得到解决,但我仍然需要能够:
- 定义服务接口
- 在可重用组件中使用该服务接口
- 为我自己的需要创建一个实现原始接口的新服务实例
- 能够使用多个组件来实现相同的服务接口,并在单个父组件中使用不同的服务实现
【问题讨论】:
标签: angularjs angular service dependency-injection components