路由更改后在服务之间切换

Switching between services after route change

我的应用程序有很多几乎相同的组件。每个组件都包含具有相似选项和不同数据系列的图表。所有数据获取和操作都在服务中进行。

我想到我不需要那么多几乎相同的组件,我将通过服务传递选项和系列。这将减少很多样板文件。但这是一个好习惯吗?有10个服务和10个组件还是10个服务和1个组件会在路由更改时更改服务更好?

这也只是理论。我试过这样做,但我一直坚持如何在路由更改后提供另一项服务,然后重新初始化组件。找不到任何相关信息,所以任何建议都会非常有帮助。

我在 StackBlitz 上重现了这个问题。

是的。最好有 1 个组件和 10 个服务

如果所有组件的内容几乎相同,您可以为所有路由重复使用相同的组件。更好的方法是使用 1 个组件和 10 个服务。

您可以通过使用传递给组件的数据作为输入的条件来决定使用哪些服务来获取数据,或者您可以使用其他服务来保存当前数据和系列。

您可以使用解析器将数据发送到路由。我对代码做了一些修改,因此您可以参数化可以将哪个服务发送到哪个路由。我并不是说这是最好的方法,但你可以试试这个。您甚至可以维护自定义服务存储,而不是每次都实例化,就像在 serviceResolvers.ts

中所做的那样

StackBlitz

//// app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import {
  Service1Resolver,
  Service2Resolver,
} from '../component/serviceResolvers';
import { TemplateComponent } from '../component/template.component';
import { AppComponent } from './app.component';

const routes: Routes = [
  {
    path: '',
    redirectTo: 'home',
    pathMatch: 'full',
  },
  {
    path: 'template',
    component: TemplateComponent,
    resolve: {
      service: Service1Resolver, // Customize your service
    },
  },
  {
    path: 'template2',
    component: TemplateComponent,
    resolve: {
      service: Service2Resolver,
    },
  },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
  providers: [Service1Resolver, Service2Resolver],
})
export class AppRoutingModule {}
/// serviceResolvers.ts
import { Injectable } from '@angular/core';
import {
  ActivatedRouteSnapshot,
  Resolve,
  RouterStateSnapshot,
} from '@angular/router';
import { Service1Service } from './service1.service';
import { Service2Service } from './service2.service';

@Injectable()
export class Service1Resolver implements Resolve<any> {
  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    return new Service1Service();
  }
}

@Injectable()
export class Service2Resolver implements Resolve<any> {
  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    return new Service2Service();
  }
}

您应该将 chartId 作为路由参数传递。这样你的路由配置就更简单、更清晰了:

  {
    path: 'template/:chartId',
    component: TemplateComponent,
  },

然后在TemplateComponent你订阅ActivatedRoute检测路由参数变化:

  constructor(
    private _service1: Service1Service,
    private _service2: Service2Service,
    private route: ActivatedRoute
  ) {}

  ngOnInit(): void {
    this.route.params.subscribe((params) => {
      const selectedChartId = +params['chartId'];
      if (selectedChartId === 1) {
        this.service = this._service1;
      } else {
        this.service = this._service2;
      }
      this.number = this.service.temp;
    });
  }

检查我根据您的代码创建的 StackBlitz:https://stackblitz.com/edit/angular-ivy-m3f5do?file=src/component/template.component.ts

将 chartId 从 1 更改为 2 以查看它是否正常工作:https://angular-ivy-m3f5do.stackblitz.io/template/1

您可以利用抽象 classes、依赖注入和工厂,让我解释一下: 首先,您可以创建一个 Service 抽象 class ,它将成为您具体服务的模型和组件中注入的令牌,然后使用 serviceFactory 注入具体服务 class 在组件中取决于运行时参数(例如路由路径)

我在这个 stackblitz

通过导航到 /template,您会看到使用了 service1 并显示了数字 1。
通过导航到 /template2,将使用 service2 并显示数字 2

如果您有任何问题,请告诉我。