如何使用多个 components/routes 在 ngOnInit 上调用服务的方法
How to call a service's method on ngOnInit with multiple components/routes
我有几条路由,不过是一个静态页面。
在每条路线(超过 50 条)上,当路线启动时,我必须在两个不同的服务上调用几个方法(以及更多)。
一个简单的工作解决方案是在每个页面上调用 ngOnInit 方法并调用上述方法。
问题在于,这意味着将相同的代码复制并粘贴到 50 个不同的文件中。复制和粘贴不好,不可维护。
打个比方:
我有页面 "FAQ"(手动分配的 ID:52)和页面 "Find Us"(手动分配的 ID:13)。这是 2 条不同的路线。
我有服务 "Editor",用于从管理面板编辑这些页面,它需要跟踪我看到的页面。
我有服务 "Cache",它检查页面之前是否已经被查询到后端或者是否需要从服务器中拉出。
这两个服务都想知道我手动分配给该路线的 ID。
此特定案例中的 ID 用于查询 database/API,但此详细信息不是以问题为中心的,不应使其他有类似问题的人的答案无效。
// Page FAQ
id: number
constructor() {
this.id = 52; // 52 is the id that I assigned to the page FAQ
}
ngOnInit () {
editorService.keepTrack(this.id);
editorService.moreMethod().notMaintainable().whatIfIChangeSomething(this.id/0);
cacheService.keepTrack(this.id);
}
// Page Find Us
id: number
constructor() {
this.id = 13; // 13 is the id that I assigned to the page Find Us
}
ngOnInit () {
editorService.keepTrack(this.id);
editorService.moreMethod().notMaintainable().whatIfIChangeSomething(this.id/0);
cacheService.keepTrack(this.id);
}
现在,这是一个简化的示例,因为我认为没有必要用与手头问题无关的细节来重载问题。
我能想到的唯一解决办法,就是做第三个服务。这将调用其他两个的方法。
因此,在每个页面中,我只需要在 ngOnInit 上调用这个单一服务方法,并将如何调用其他两个服务的实现留给第三个服务。
这将最大限度地减少复制和粘贴,并将实现留在一个可维护的文件中。
打个比方:
// Page FAQ v2
id: number
constructor() {
this.id = 52;
}
ngOnInit() {
inceptionService.doStuff(this.id);
}
// Page Find Us v2
id: number
constructor() {
this.id = 13;
}
ngOnInit() {
inceptionService.doStuff(this.id);
}
// InceptionService
export class InceptionService {
doStuff(data) {
editorService.keepTrack(data);
editorService.moreMethod().notMaintainable().whatIfIChangeSomething(data/0);
cacheService.keepTrack(data);
}
}
问题是:
有一个更好的方法吗?我有一种感觉,我没有用最好的方法来做这件事。
感觉还是在滥用服务。
您可以订阅路由事件并从那里调用您的方法。 (参见 )
这也适用于服务。
您可以为这些路由创建一个基础 class,并使您的组件继承自该基础 class。
export class BaseComponent {
ngOnInit() {
//your service calls
}
}
export class MyStaticComponent1 extends BaseComponent {
ngOnInit() {
super.ngOnInit();
//component specific calls
}
}
Michal Dymel 的替代方案是有效的,并且可以通过比我的 "InceptionService" 更好的方法满足我的所有需求,但我觉得 Günter Zöchbauer 的答案使用了更好、更易于维护且更 Angular 的方法,尽管他的回答不完整。
Günter Zöchbauer 的回答也让我找到了 Alex Rickabaugh @alxhub 帮助我最终确定的其他解决方案。
这里我指的是angular-cli结构。
在 app.component.html 上替换
<router-outlet>
与
<router-outlet (activate)="newComponentActivated($event)">
在 app.component.ts
newComponentActivated(component) {
// Updating tracked page ID
this.editorService.updateCurrentPage(component);
}
在"editor service"
updateCurrentPage(component) {
console.log(component);
}
现在,每次路由更改时,都会有一个事件通知编辑器服务,并提供组件的副本,包括参数和方法。
这意味着无需在路由组件中扩展或实现任何内容。
我有几条路由,不过是一个静态页面。
在每条路线(超过 50 条)上,当路线启动时,我必须在两个不同的服务上调用几个方法(以及更多)。
一个简单的工作解决方案是在每个页面上调用 ngOnInit 方法并调用上述方法。
问题在于,这意味着将相同的代码复制并粘贴到 50 个不同的文件中。复制和粘贴不好,不可维护。
打个比方:
我有页面 "FAQ"(手动分配的 ID:52)和页面 "Find Us"(手动分配的 ID:13)。这是 2 条不同的路线。
我有服务 "Editor",用于从管理面板编辑这些页面,它需要跟踪我看到的页面。
我有服务 "Cache",它检查页面之前是否已经被查询到后端或者是否需要从服务器中拉出。
这两个服务都想知道我手动分配给该路线的 ID。
此特定案例中的 ID 用于查询 database/API,但此详细信息不是以问题为中心的,不应使其他有类似问题的人的答案无效。
// Page FAQ
id: number
constructor() {
this.id = 52; // 52 is the id that I assigned to the page FAQ
}
ngOnInit () {
editorService.keepTrack(this.id);
editorService.moreMethod().notMaintainable().whatIfIChangeSomething(this.id/0);
cacheService.keepTrack(this.id);
}
// Page Find Us
id: number
constructor() {
this.id = 13; // 13 is the id that I assigned to the page Find Us
}
ngOnInit () {
editorService.keepTrack(this.id);
editorService.moreMethod().notMaintainable().whatIfIChangeSomething(this.id/0);
cacheService.keepTrack(this.id);
}
现在,这是一个简化的示例,因为我认为没有必要用与手头问题无关的细节来重载问题。
我能想到的唯一解决办法,就是做第三个服务。这将调用其他两个的方法。
因此,在每个页面中,我只需要在 ngOnInit 上调用这个单一服务方法,并将如何调用其他两个服务的实现留给第三个服务。
这将最大限度地减少复制和粘贴,并将实现留在一个可维护的文件中。
打个比方:
// Page FAQ v2
id: number
constructor() {
this.id = 52;
}
ngOnInit() {
inceptionService.doStuff(this.id);
}
// Page Find Us v2
id: number
constructor() {
this.id = 13;
}
ngOnInit() {
inceptionService.doStuff(this.id);
}
// InceptionService
export class InceptionService {
doStuff(data) {
editorService.keepTrack(data);
editorService.moreMethod().notMaintainable().whatIfIChangeSomething(data/0);
cacheService.keepTrack(data);
}
}
问题是:
有一个更好的方法吗?我有一种感觉,我没有用最好的方法来做这件事。
感觉还是在滥用服务。
您可以订阅路由事件并从那里调用您的方法。 (参见
这也适用于服务。
您可以为这些路由创建一个基础 class,并使您的组件继承自该基础 class。
export class BaseComponent {
ngOnInit() {
//your service calls
}
}
export class MyStaticComponent1 extends BaseComponent {
ngOnInit() {
super.ngOnInit();
//component specific calls
}
}
Michal Dymel 的替代方案是有效的,并且可以通过比我的 "InceptionService" 更好的方法满足我的所有需求,但我觉得 Günter Zöchbauer 的答案使用了更好、更易于维护且更 Angular 的方法,尽管他的回答不完整。
Günter Zöchbauer 的回答也让我找到了 Alex Rickabaugh @alxhub 帮助我最终确定的其他解决方案。
这里我指的是angular-cli结构。
在 app.component.html 上替换
<router-outlet>
与
<router-outlet (activate)="newComponentActivated($event)">
在 app.component.ts
newComponentActivated(component) {
// Updating tracked page ID
this.editorService.updateCurrentPage(component);
}
在"editor service"
updateCurrentPage(component) {
console.log(component);
}
现在,每次路由更改时,都会有一个事件通知编辑器服务,并提供组件的副本,包括参数和方法。
这意味着无需在路由组件中扩展或实现任何内容。