Я начал работать над проектом angular 8, в котором два родственных компонента должны обмениваться данными. До сих пор подход состоял в том, чтобы EventEmitter был в родительской службе. Затем дочерние компоненты вызвали методы emit для этих эмиттеров, чтобы передать данные другому брату. Вот пример случая:
Shared Service: (плохо)
@Injectable()
export class DocumentViewerService {
public readonly annotationDeletedInAnnotationPanel = new EventEmitter<string>();
Дочерний компонент: (плохо)
this.documentViewerService.annotationDeletedInAnnotationPanel.emit(annotationId);
Однако я обнаружил несколько онлайн-источников ( 1 , 2 ), которые утверждают, что использование EventEmitters в Сервисах является плохой практикой.
Вместо этого большинство онлайн-источников ( 3 , 4 ) предлагают шаблон, использующий Темы и общие службы для родственного общения.
Общий сервис: (хорошо)
@Injectable()
export class DocumentViewerService {
private deletedAnnotationInAnnotationPanel$ = new Subject<string>();
public readonly deletedAnnotationInPanel$ = this.deletedAnnotationInAnnotationPanel$.asObservable();
deleteAnnotationInPanel(annotationId: string) {
this.deletedAnnotationInWebViewer$.next(annotationId);
}
Дочерний компонент: (хорошо)
this.documentViewerService.deleteAnnotationInPanel(id);
Оба подхода оставляют у меня несколько вопросов:
- Почему плохой практикой является использование EventEmitters в Service . Вам не нужно помещать тег @Output, и он будет действовать подобно наблюдаемому при вызове с помощью emit в одном из дочерних элементов.
- Какая причина сделать Субъект личным в предположительно лучшем подходе? Дочерние компоненты по-прежнему могут изменять значения, вызывая предоставленный метод deleteAnnotationInPanel (в приведенном выше примере).
В чем разница в создании объекта Subject deleteAnnotationInAnnotationPanel $ Приватное и публичное c Только для чтения . Последний позволит всем подписаться и вызвать .next, но не изменять инициализацию. Вместо пяти строк кода у меня была бы только одна:
publi c readonly deleteAnnotationInPanel $ = new Subject ();
Ни один из сетевых источников не кажется объяснить, почему нужно сделать Предмет закрытым с помощью метода установки и дополнительной публикации, доступной для детей.
Надеюсь, вы можете дать мне несколько веских аргументов или понять, почему один должен быть предпочтительнее других. Заранее спасибо за поддержку!