【问题标题】:Switching between services after route change路由更改后在服务之间切换
【发布时间】:2021-09-17 13:45:24
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: angular angular-routing


    【解决方案1】:

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

    我在 stackblitz 中做到了这一点

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

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

    【讨论】:

    • 这是我一直在寻找的,但是有没有办法在路线更改时破坏以前的服务?
    • @abellay 我认为如果您在组件本身中提供服务,它们会被直接删除,不是吗?再次检查我添加了增量方法的stackblitz,您可以增加然后更改模板,临时变量将被重新初始化
    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

      您可以使用解析器将数据发送到路由。我已经稍微修改了代码,以便您可以参数化哪些服务可以发送到哪个路由。我不是说这是最好的方法,但你可以试试这个。您甚至可以维护自定义的服务存储,而不是像 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();
        }
      }
      

      【讨论】:

        【解决方案4】:

        您应该将 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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-12-07
          • 2019-12-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-09-12
          • 2017-12-07
          • 2013-02-28
          相关资源
          最近更新 更多