【问题标题】:Getting ExpressionChangedAfterItHasBeenCheckedError when updating view更新视图时出现 ExpressionChangedAfterItHasBeenCheckedError
【发布时间】:2021-05-10 16:45:01
【问题描述】:

我收到以下错误:

当我尝试使用 *ngIf 更新视图(在图标显示上切换)时。

这是我的 .ts:

@Component({
    selector: 'app-orders',
    templateUrl: './orders.component.html',
    styleUrls: ['./orders.component.css'],
    encapsulation: ViewEncapsulation.None
})
export class OrdersComponent implements OnInit, OnDestroy {

    loadedPendingOrders: Order[] = [];
    loadedProcessedOrders: Order[] = [];
    loadedDeliveredOrders: Order[] = [];
    loadedCancelledOrders: Order[] = [];
    pendingOrderTimelines: string[] = [];
    deliveredOrderTimelines: string[] = [];
    cancelledOrderTimelines: string[] = [];
    isDeliverySlotsActive: boolean;
    searchTerm: string;
    newOrderStatus: string;
    private subscription: Subscription;

    constructor(private ordersService: OrdersManagerService, private shopPreferencesService: ShopManagerService, private apiManager: ApiManagerService) {}

    ngOnInit(): void {
        this.subscription = timer(0, 5000).pipe(
            switchMap(() => this.apiManager.fetchShopOrders())
            ).subscribe(orders => {
                this.isDeliverySlotsActive = this.shopPreferencesService.isDeliverySlotsActive();
                const loadedOrders: OrdersList = orders;
                /* do stuff with orders */
        });
    }

    onNewOrderAdded(status: string){
        this.newOrderStatus = status;
    }
    ....
}

这是我的 .html:

<div id="tab-group">
    <mat-tab-group dynamicHeight animationDuration="400ms">
        <mat-tab>
            <ng-template mat-tab-label>
                <span>Pending</span>
                <img src="../../assets/my-orders/blue-tiny.svg" *ngIf="newOrderStatus == 'PENDING'">
            </ng-template>
            <app-orders-list
                [orders]="loadedPendingOrders"
                [timelines]="pendingOrderTimelines"
                [isDeliverySlotsActive]="isDeliverySlotsActive"
                [searchTerm]="searchTerm"
                (newOrderStatus)="onNewOrderAdded($event)"
            ></app-orders-list>
            ...
        </mat-tab>
    </mat-tab-group>
</div>

视图正在正确更新。但是,错误仍然被抛出。怎么会?

提前致谢。

【问题讨论】:

  • 错误的堆栈跟踪应该指向模板中触发错误的特定值。我有一种感觉,这是由 dynamicHeight 指令引起的,但如果没有代码,它只是一个猜测。是哪一个?
  • @Stavm 指向这一行:&lt;img src="../../assets/my-orders/blue-tiny.svg" *ngIf="newOrderStatus === 'PENDING'"&gt;
  • @Stavmn 我已经用错误图片更新了问题。现在会检查是否是因为dynamicHeight
  • @Stavm 删除 dynamicHeight 并没有修复它。这是一个奇怪的错误,因为视图正在正确更新,但仍然抛出错误。
  • 你可以尝试删除(newOrderStatus)="onNewOrderAdded($event)"看看是否发生

标签: angular typescript error-handling angular-ng-if


【解决方案1】:

发生这种情况是因为您在组件生命周期完成之前更改了newOrderStatus。该值以undefined 开头,然后将一些数据传递给子级,然后子级将下一个值发送回父级。

这通常是 Angular 应用程序中的代码异味。您的孩子正在口授父母的状态,父母应该知道自己的状态。

Here's a contrived example. 我的父组件将一些值传递给子组件,子组件然后决定某个字符串值并发出它,然后父组件使用它来决定要显示哪个div。打开控制台查看可怕的ExpressionChangedAfterItHasBeenCheckedError 错误。

要解决此问题,我建议将您的状态及其计算方式(即状态、订单等)与您的组件(您的 Orders 和 OrdersList 组件)分开。我将实现一个服务,该服务具有一些用于操作状态的功能和一个发出组件可以订阅的 observable。

【讨论】:

  • 是的,这正是您描述的场景。我很欣赏你的建议,但你对在ngAfterViewChecked 中做this.cdRef.detectChanges() 有什么想法?我一直在阅读有关此错误的更多信息,并且此建议似乎经常出现。我已经尝试过了,它有效,但我怀疑这是处理这个问题的最糟糕的方法......对于像我这样的新手初级开发人员来说,最不痛苦的解决方案是什么?
  • 我自己确实使用过它,它可能会使错误消失。事实上,当您使用 --prod 标志构建时,甚至不会出现该错误。这实际上只是一个警告,提示某些可能无法正常工作。但是,就像我在帖子中所说的那样,这绝对是一种代码味道。我仍然认为一点点重构会大有帮助,并产生更多可维护和可测试的代码。
猜你喜欢
  • 2011-10-01
  • 2017-02-04
  • 1970-01-01
  • 2018-01-17
  • 1970-01-01
  • 1970-01-01
  • 2013-05-01
  • 2020-09-02
  • 1970-01-01
相关资源
最近更新 更多