【问题标题】:ViewChild vs Input/Output in Angular, any Disadvantages or capability difference?ViewChild 与 Angular 中的输入/输出,有什么缺点或能力差异吗?
【发布时间】:2020-01-01 17:51:38
【问题描述】:

我正在阅读有关 Angular ViewChild 并与输入/输出参数进行比较的信息。只是好奇 Viewchild 是否有任何缺点,或者无法做 Input/Output 可以做的事情?

看来 ViewChild 是首选路线,因为所有参数现在都位于 Typescript 中。这似乎比混合/混淆到 html 标记中更好。业务/数据逻辑参数现在可以放在一个地方。

查看孩子

@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;
}

输入/输出

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

【问题讨论】:

  • 如果您使用@Input()@Output(),那么对于演示组件来说完全没问题。只要数据来自智能组件,您就可以在任何地方使用此演示文稿而无需担心。因此,例如...如果您将数据传递给表示组件,那么它将显示它,或者如果您没有传递任何值,它将根本不显示任何内容。当您可以将相同的组件用于addedit 操作时,此场景非常有用。
  • 不知道为什么这个问题被否决,似乎是一个合理的问题

标签: angular typescript angular8


【解决方案1】:

在已回答的内容之上添加。在HTML 上使用[ ]( ) 本身对其实现非常有描述性。 Angular 的整个概念围绕着 HTML component 展开。

当您开始将 DOM 分解为 components 时,它的可重用性会增加。当您使用此类组件时(例如我们使用 angular material ),您希望用户(将其作为库导入)知道作为 Input 的所有参数以及作为 Output 发出的所有参数。您在代码中看到这样的组件,您就会立即知道是什么使它起作用。

没有适当的表示,用户怎么知道? Take a look at this example

使用@Input 和@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>

没有

<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>

您更喜欢阅读哪个代码?

另外,您将如何处理(click)(keyup)[routerLink] 等简单事件。

这些事情可以通过一些变通方法来实现,但它是否像现在这样可读且对开发人员友好?

有时,我们需要创建隔离的功能,以便我们可以轻松地了解其存在于代码中的原因。适用于所有语言的软件

【讨论】:

  • 很好的解释 :) thnks
  • @katmanco : 很高兴为您提供帮助 :) 感谢您放弃评论
【解决方案2】:

说实话,这取决于你的喜好,我通常使用 ViewChild/ren 进行 dom 操作,类似于我们过去使用 jQuery 来更改原生 HTML 元素,并使用 input/output 进行数据绑定和控制状态来自父组件的子组件,以使他保持孤立和无状态。

角度文档中的示例 - https://angular.io/api/core/ViewChild

您可以看到 ID 属性作为窗格组件的输入传递,而可见性是从父级管理的。

现在我们可以更改它,以防我们在pane 中有一个按钮来切换可见性,然后您将添加一个outputpane 组件,该组件向父组件发出切换状态更改,并且父母仍然会利用viewChild 来改变孩子的状态。

就技术问题和缺点而言,尝试自己设置子组件属性不是被动的,也不会像input/output 的工作方式一样触发 Angular 的更改检测(Angular 默认监视这些属性)。

测试这样的组件很困难,因为子组件不知道他的状态和父组件负责的更改,您必须将它们作为一个整体进行测试。

一般来说,以这种方式更改组件属性是不好的做法,因为它会破坏 Angular 的 changeDetection 并且您需要使用 changeDetectorRef 手动管理它

【讨论】:

  • 这不是 ViewChild/ren 的真正目的,您在另一个问题上批准的答案不是您应该在 Angular 中使用的做法,它打破了隔离和模块化的整个概念。
  • @DanielNetzer:你有有效的积分+1,但你能提供支持trying to set the child component properties by yourself isn't reactive and won't trigger Angular's change detection的例子吗?看一下stackblitz.com/edit/…,可见性的变化就被检测到了。我想看一个在ViewChild 的情况下不触发ChangeDetection 的示例
  • changeDetection 的角度取决于检查属性值是否已更改,无论以任何 @Directive 或其他方式。如果您将某些内容从一种状态更改为其他角度火灾 changeDetection 进行更新在视图上正确声明。在@ViewChild() 方式中,我们必须使用ChangeDetectionReference.detectChanges() 明确告诉angular 来检测变化,而在@Input() 方式中,angular 会隐式处理detectionChanges ...所以它会触发onChanges() 生命周期钩子,我们可以获得财产值改变当前、前一个的状态...
  • @ShashankVivek 在我 99% 的应用程序中我定义了 changeDetectionStrategy: onPush,因此 Angular 不会检查整个树,然后它就会失败。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-17
  • 1970-01-01
  • 2019-08-20
  • 2012-05-09
  • 2011-10-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多