Переключение между службами после изменения маршрута

#angular #angular-routing

Вопрос:

В моем приложении есть много компонентов, которые почти одинаковы. Каждый компонент содержит диаграмму с аналогичными параметрами и различными рядами данных. Вся выборка и обработка данных происходит в сервисе.

Мне пришла в голову идея, что мне не нужно так много почти одинаковых компонентов, и я просто передам опции и серии через сервис. Это уменьшит количество шаблонов. Но является ли это хорошей практикой? Лучше ли иметь 10 служб и 10 компонентов или 10 служб и 1 компонент, которые изменят обслуживание при изменении маршрута?

К тому же это всего лишь теория. Я пытался это сделать, но застрял на том, как предоставить другую услугу после изменения маршрута, а затем повторно запустить компонент. Не смог найти никакой информации об этом, поэтому любой совет был бы очень полезен.

Я воссоздал эту проблему на StackBlitz.

Ответ №1:

Вы можете использовать абстрактные классы, инъекции зависимостей и заводы, поясню: во-первых, вы можете создать Service абстрактный класс, который будет модель для конкретных служб и вводят маркер в свой компонент, а затем использовать serviceFactory для введения конкретный класс обслуживания в компоненте в зависимости от выполнения параметров (например, путь следования к примеру)

Я сделал это в этом стакблитце

Вы увидите, что при переходе к /шаблону используется сервис1 и отображается число 1.
И при переходе к /шаблону2 используется сервис2 и отображается число 2

Дайте мне знать, если у вас возникнут вопросы.

Комментарии:

1. Это то, что я искал, но есть ли способ уничтожить предыдущую службу при изменении маршрута?

2. @abellay Я думаю, что они удаляются напрямую, если вы предоставляете свои услуги в самом компоненте, нет? Проверьте еще раз stackblitz, я добавил метод приращения, и вы можете увеличить, а затем изменить шаблон, временный параметр будет повторно инициализирован

Ответ №2:

ДА. Хорошей практикой является наличие 1 компонента и 10 услуг

Если содержимое всех компонентов почти одинаково, вы можете повторно использовать один и тот же компонент для всех ваших маршрутов. лучший подход-использовать 1 компонент и 10 сервисов.

Вы можете решить, какие службы использовать для извлечения данных, используя условия, использующие данные, переданные компоненту в качестве входных данных, или вы можете использовать другую службу для хранения текущих данных и рядов.

Ответ №3:

Вы можете использовать распознаватели для отправки данных на маршрут. Я немного изменил код, чтобы вы могли указать, какая служба может быть отправлена по какому маршруту. Я не говорю, что это лучший способ, но вы можете попробовать это. Вы даже можете поддерживать собственное хранилище служб вместо создания экземпляров каждый раз, как это было сделано в serviceResolvers.ts

Стакблитц

 //// 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;
    });
  }
 

Проверьте этот стекблитц, который я создал на основе вашего кода: https://stackblitz.com/edit/angular-ivy-m3f5do?file=src/component/template.component.ts

Измените диаграмму с 1 на 2, чтобы она работала: https://angular-ivy-m3f5do.stackblitz.io/template/1