Búsqueda de sitios web

typescript - ViewChild vs Input/Output en Angular, ¿alguna desventaja o diferencia de capacidad?


Estoy leyendo sobre Angular ViewChild y comparándolo con los parámetros Input/Output. Solo tengo curiosidad si ViewChild tiene alguna desventaja, o si no puede hacer algo que Input/Output sí puede.

Parece que ViewChild es la ruta preferida, ya que todos los parámetros ahora se encuentran en Typescript. Esto parece mejor que mezclar/revolver en el marcado HTML. Los parámetros de lógica de negocio/datos ahora pueden estar en un solo lugar.

ViewChild

@ViewChild(AddressTypeDropdownComponent, { static: false }) child: AddressTypeDropdownComponent;

ngAfterViewInit() {
  // Subscribe to the child component event
  this.child.addressTypeChange.subscribe(value => {
    console.log(value);
  });
}

someMethod() {
  // Set the input values of the child component
  this.child.addressTypeDefaultItem = someValue1;
  this.child.selectedAddressType = someValue2;
}

Entrada/Salida

<app-address-type-dropdown 
    (addressTypeChange)="addressTypeChangeEvent($event)"
    [addressTypeDefaultItem]="someValue1"
    [selectedAddressType]="someValue2">
</app-address-type-dropdown>

Respuesta #1

Agregando a lo que ya se ha respondido. El uso de [ ] y ( ) en HTML es muy descriptivo para su implementación. Todo el concepto de Angular gira en torno a componente HTML.

Cuando comienzas a descomponer el DOM en componentes, se incrementa su reutilización. Cuando utilizas dichos componentes (como usamos Angular Material), quieres que el usuario (que los importa como bibliotecas) sepa qué parámetros recibe como Input y qué parámetros emite como Output. Ves esos componentes en el código y de inmediato sabes qué cosas los hacen funcionar.

Sin una representación adecuada, ¿cómo puede un usuario saber? Echa un vistazo a este ejemplo

Con @Input y @Output:

<button mat-raised-button (click)="addColumn()"> Add column </button>
<button mat-raised-button (click)="removeColumn()"> Remove column </button>
<button mat-raised-button (click)="shuffle()"> Shuffle </button>

<table mat-table [dataSource]="data" class="mat-elevation-z8">
  <ng-container [matColumnDef]="column" *ngFor="let column of displayedColumns">
    <th mat-header-cell *matHeaderCellDef> {{column}} </th>
    <td mat-cell *matCellDef="let element"> {{element[column]}} </td>
  </ng-container>

  <tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
  <tr mat-row *matRowDef="let row; columns: columnsToDisplay;"></tr>
</table>

Sin

<button mat-raised-button #add> Add column </button>
<button mat-raised-button #remove> Remove column </button>
<button mat-raised-button #shuffle> Shuffle </button>

<table mat-table class="mat-elevation-z8">
  <ng-container *ngFor="let column of displayedColumns">
    <th mat-header-cell *matHeaderCellDef> {{column}} </th>
    <td mat-cell *matCellDef="let element"> {{element[column]}} </td>
  </ng-container>

  <tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
  <tr mat-row *matRowDef="let row; columns: columnsToDisplay;"></tr>
</table>

¿Qué código preferirías leer?

Además, ¿cómo manejarás eventos simples como (click), (keyup) o [routerLink].

Estas cosas se pueden lograr mediante algún método alternativo, pero ¿sería legible y amigable para desarrolladores tal como está ahora?

A veces, necesitamos crear funcionalidades segregadas para que podamos entender fácilmente la razón de su existencia en el código. Es aplicable a todos los lenguajes de software.

Respuesta #2

Depende de tus preferencias, para ser honesto, yo normalmente trabajo con ViewChild/ren para manipulaciones del DOM similares a lo que solíamos hacer con jQuery para cambiar el elemento HTML nativo, y usando input/output para el enlace de datos y controlar el estado de un componente hijo desde el padre para mantenerlo aislado y sin estado.

ejemplo de la documentación de Angular - https://angular.io/api/core/ViewChild

puedes ver que la propiedad ID se está pasando como un input para el componente de panel, mientras que la visibilidad se gestiona desde el componente padre.

ahora podríamos haberlo cambiado en caso de que tuviéramos un botón dentro del pane que alterna la visibilidad y luego agregarás un output al componente pane que emite el cambio de estado del toggle al padre, y aún así el padre utilizará el viewChild para cambiar el estado del hijo.

En términos de problemas tecnológicos y desventajas, intentar establecer las propiedades del componente hijo por ti mismo no es reactivo y no activará la detección de cambios de Angular de la misma manera que funciona input/output (Angular observa esas propiedades por defecto).

Probar un componente así es difícil ya que el componente hijo no está consciente de su estado y de los cambios que el padre maneja, tendrás que probarlos como uno solo.

En general, es una mala práctica cambiar los atributos del componente de esta manera, ya que romperá el changeDetection de Angular y tendrás que gestionarlo manualmente con changeDetectorRef

Artículos relacionados