Angular - Инкапсулировать сервис внутри компонента - это плохая практика? - PullRequest
0 голосов
/ 10 ноября 2019

Давайте предположим, что у меня есть SoccerFieldComponent, у которого есть провайдер, который назвал SoccerFieldService

SoccerFieldComponent:

@Component({
 providers: [SoccerFieldService]
})
class SoccerFieldComponent extends Component {
//yada yada....
}

SoccerFieldService:

class SoccerFieldService {
//a lot of observables/functions that related to the soccer field component
}

Теперь давайте предположим, что SoccerFieldComponent может использоваться несколько раз в моей сложной системе, единственное, что будет отличаться, - это компонент, который его оборачивает, давайте дадим ему имя StadiumComponent

StadiumComponent:

@Component({
 template: "some-complex-template-that-contains-stadium-field-component.html"
})
class StadiumComponent {
}

Я действительно хотел бы представить некоторые из SoccerFieldService данных вне SoccerFieldComponent, чтобы StadiumComponent мог их использовать.

Мое текущее решение:

Внутри StadiumComponent:

@ViewChild(SoccerFieldComponent, {static: false})
    set soccerFieldComponent(componentRef: SoccerFieldComponent) {
        if (componentRef) {
            this.soccerFieldComponentRef = componentRef;
            this.changeDetection.detectChanges();
        }
    }

Внутри SoccerFieldComponent:

get currentScore$(): Observable<string> {
        return this.soccerFieldService.currentScore$.pipe(
            distinctUntilChanged(),
        );
    }

Теперь яМожно получить доступ через компонент к конкретным наблюдаемым внутри службы.

Есть еще идеи?

Ответы [ 2 ]

0 голосов
/ 10 ноября 2019

Я предлагаю НЕ предоставлять услуги напрямую на уровне компонентов. Вместо этого оберните все необходимые компоненты, сервисы, каналы, директивы и т. Д. (Они работают как один блок) как модуль.

Мой подход будет следующим:

@Injectable()
class SoccerFieldService {
  //a lot of observables/functions that related to the soccer field component

  currentScore$() {
    return of(0);
  }
}

@Component({
  providers: [SoccerFieldService]
})
class SoccerFieldComponent extends Component {

  constructor(soccerFieldService: SoccerFieldService)

  get currentScore$(): Observable<string> {
    return this.soccerFieldService.currentScore$.pipe(
      distinctUntilChanged(),
    );
  }
}

@Component({
  template: "some-complex-template-that-contains-stadium-field-component.html"
})
class StadiumComponent {
  @ViewChild(SoccerFieldComponent, { static: false })
  set soccerFieldComponent(componentRef: SoccerFieldComponent) {
    if (componentRef) {
      this.soccerFieldComponentRef = componentRef;
      this.changeDetection.detectChanges();
    }
  }
}

@NgModule({
  imports: [
    CommonModule
  ],
  declarations: [
    StadiumComponent,
    SoccerFieldComponent
  ],
  exports: [
    StadiumComponent,
    SoccerFieldComponent
  ],
  providers: [
    SoccerFieldService
  ]
})
export class SoccerFieldModule {
}

Импорт модуля SoccerFieldModuleгде требуется.

0 голосов
/ 10 ноября 2019

Вы заново изобретаете колесо. Поскольку SoccerFieldService - это сервис, который вы хотите использовать в нескольких местах, сделайте его инъекционным и внедрите его там, где он вам нужен. Вы можете внедрить один и тот же экземпляр службы в StadumComponent и SoccerFieldComponent. Нет необходимости (дух - это просто плохой дизайн) выставлять serivce только через компонент, чтобы позволить другим компонентам использовать его. Эти компоненты должны использовать сервис напрямую.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...