错误:检查表达式后,表达式已更改-在构造函数中

问题描述

这是在我的html文件中:

  <div id="my-div" [ngClass]="hasSetting ? 'my-container' : 'opacity-div my-container'">    
    <dx-load-panel
      #loadPanel
      [(visible)]="!hasSetting" >
    </dx-load-panel>
  </div>

这是我的组件:

export class TurnoverWidgetComponent {

  departments: Dropdownoption[] = [];
  hasSetting: boolean;

  constructor(
    private myService: MyService
  ) {

    forkJoin(
      this.myService.hasSetting(),this.myService.getDepartments()
    ).subscribe(
      ([hasSetting,departments]) => {
        this.hasSetting = hasSetting;

          this.departments = departments.map(item => {
            return {
              id: item.id,name: item.name
            }
          });
      }
    );
  }
}

然后我得到了错误Error:Expression,在构造函数中进行了更改,它从true变为false,反之亦然。根据我的研究,该错误发生在组件初始化之后发生的事件中,但是我没有此类事件,我的更改发生在构造函数中。我尝试将其放在oninit事件中,发生同样的事情。

解决方法

我认为您应该在设置超时下提供您的逻辑。这样可以解决您的问题。

ngAfterViewInit() {
     forkJoin(
      this.myService.hasSetting(),this.myService.getDepartments()
    ).subscribe(
      ([hasSetting,departments]) => {
        
    setTimeout(() => {
       this.hasSetting = hasSetting;
    },200);
          this.departments = departments.map(item => {
            return {
              id: item.id,name: item.name
            }
          });
      }
    );
,

当组件已经检查了更新并想要更新视觉效果时,以及再次更新之前检查并发现数据不相同时,就会发生这种情况。 非常烦人。

但是您可以稍微改变一下策略以摆脱它(我希望。我没有测试过)

您不需要订阅数据,请让异步管道执行此操作,因为它会同时使用数据,并且在您更改为其他路由时也会取消订阅, 只需使用运算符以您喜欢的方式对数据进行整形并将其提供给html。

  data$: Observable<{hasSetting: boolean; departments: DropdownOption[] }>
  constructor(
    private myService: MyService
  ) {

    this.data$ = forkJoin(
      this.myService.hasSetting(),this.myService.getDepartments()
    ).pipe(map(x=>{
      return {
        hasSetting: x[0],departments: x[1]
      }
    }))
  }
  <div *ngIf="data$ | async as data" [ngClass]="data.hasSetting ? 'my-container' : 'opacity-div my-container'">    
    <dx-load-panel
      #loadPanel
      [visible]="!hasSetting" >
    </dx-load-panel>
  </div>
,

您需要了解,当我们从中获得答案时,我们将进行http调用并更改组件变量。在开发模式下,angular两次调用更改检测以检查值是否未更改,以确保代码不会表现异常。在这里,Angular抱怨自第一次检查组件值后,这些值已更改。

此处更新了代码,以确保在我们在http回调中更改角度后,角度检测到更改:

    export class TurnoverWidgetComponent implementes OnInit {
    
      departments: DropdownOption[] = [];
      hasSetting: boolean;
    
      constructor(
        private myService: MyService,private cd: ChangeDetectorRef,) {}

      ngOnInit() {

        forkJoin(
          this.myService.hasSetting(),this.myService.getDepartments()
        ).subscribe(
          ([hasSetting,departments]) => {
            this.hasSetting = hasSetting;
    
              this.departments = departments.map(item => {
                return {
                  id: item.id,name: item.name
                }
              });
            this.cd.detectChanges(); // this will tell angular that we changed something and explicitly invoke change detection.
          }
        );
     }
    }