web-dev-qa-db-fra.com

Angular - @Input and @Output vs. Injectable Service

Je me demande où sont les différences entre @Input/@Output Dans les composants parents/enfants et en utilisant des services qui ne sont instanciés qu'une fois avec la dépendance Injection@Injectable(). Ou y a-t-il des différences en plus des entrées/sorties ne peuvent être utilisées que dans les compositions parent/enfant.

Exemple suivant pour une meilleure visualisation:

Avec @Input:

<parent-comp>
   <child-comp [inputFromParent]="valueFromParent"></child-comp>
</parent-comp>

ChildComponent:

@Component({
  selector: 'child-comp',
  template: ...
})
export class ChildComponent {
  @Input() public inputFromParent: string;
}

Avec injection de dépendance

@Injectable()
export class Service {
   private value: string;

public get value(): string {
   return value;
}

public set value(input): void {
   value = input;
}

}

Maintenant, nous pouvons définir la valeur dans la composition parent. et obtenir la valeur dans la composition enfant avec injection de dépendance. ChildComponent:

@Component({
  selector: 'child-comp',
  template: ...
})
export class ChildComponent {
  private value: string;
  constructor(private service: Service) {
  this.value = this.service.getValue;
}

}

Même si la première approche semble plus simple, j'ai reconnu l'utilisation de 3-4 propriétés carriyng via la composition parent/enfant. avec @Input/@Output rend le tamplete très déroutant et maladroit.

10
MarcoLe

Pas exactement une question avec une réponse définie, mais ...

@Input et @Output sont utiles si la communication entre un parent et un enfant n'est que cela, entre un parent et un enfant. Il ne serait pas logique d'avoir un service qui conserve des données singleton pour seulement 2 composants (ou pour autant que les grands-parents profondément imbriqués -> parent -> composants enfants le soient).

Ils sont également utiles si votre parent doit réagir à un changement de l'enfant. Par exemple, en cliquant sur un bouton dans un composant enfant qui appelle une fonction dans le parent:

<my-child-component (myOutputEmitter)="reactToChildChange($event)"></my-child-component>

Et en parent:

reactToChildChange(data: any) {
  // do something with data
}

Si vous passez plusieurs @Input propriétés à un enfant et que vous souhaitez ranger un modèle, vous pouvez alors définir une interface pour l'entrée et la transmettre à la place. par exemple.

export interface MyChildProperties {
   property?: any;
   anotherProperty?: any;
   andAnotherProperty?: any;
}

Ensuite, vous pouvez transmettre une définition à votre enfant, qui est définie à partir du parent:

childProperties: MyChildProperties = {
    property: 'foo',
    anotherProperty: 'bar',
    andAnotherProperty: 'zoob'
}

Votre composant enfant peut alors avoir:

@Input properties: MyChildProperties;

et votre modèle devient:

<my-child-component [properties]="childProperties"></my-child-component>

Votre enfant peut accéder à ces propriétés à partir de properties.property, properties.anotherProperty, etc.

Nettoyez, rangez et vos données sont désormais contenues dans les composants qui doivent communiquer.

Cependant, les services doivent être utilisés lorsque plusieurs composants ont besoin d'accéder à des données en lecture/écriture sur l'ensemble de votre application. Considérez un UserService par exemple, où de nombreux composants différents doivent pouvoir accéder à l'utilisateur actuellement connecté. Dans ce cas, un service est raisonnable, car c'est un singleton, donc une fois que vous avez défini votre utilisateur connecté, tous les composants qui injectent UserService peuvent accéder à ses données et fonctions.

De même, si vous deviez utiliser un service pour réagir au changement, vous vous retrouveriez à écrire des services avec des observables afin que vos composants puissent s'abonner aux modifications des données. Les émetteurs d'événements vous donnent déjà ce modèle avec @Output Comme montré ci-dessus.

S'il s'agissait d'une simple communication parent -> enfant, cela ne représente pas de frais généraux inutiles et devrait être évité.

Cela dit, si vous utilisez des services pour gérer l'état global, vous feriez mieux d'utiliser une forme de gestion d'état telle que ngrx

21
prettyfly