ExpressionChangedAfterItHasBeenCheckedError:Unable to detect

ExpressionChangedAfterItHasBeenCheckedError:Unable to detect

我有一个 angular 4 应用程序。

app.component.html看起来像这样

<!--The content below is only a placeholder and can be replaced.-->
<loading-bar color="#FF0000" [height]="3" [animationTime]="0.3" [runInterval]="100" [progress]="0"></loading-bar>
<div class="app app-header-fixed" value="test">
    <app-header *ngIf="header" name="app_header"></app-header>

    <app-left-menu *ngIf="leftmenu" name="app_leftMenu"></app-left-menu>
    <div id="content" class="app-content abc_plain_wraper" role="main">
        <router-outlet></router-outlet>
    </div>

    <app-right-menu *ngIf="rightmenu"  name="app_rightMenu"></app-right-menu>

</div>

基本上在登录时它们是隐藏的,在成功登录后它们在注销时再次可见它们是隐藏的。

为此,我有一个 mange_component 服务,它在 header、右菜单和左菜单的值发生变化时发出事件。

管理组件服务方法

     import { Component, NgModule, VERSION, Injectable, Output, EventEmitter} from '@angular/core';
import { ComponentStatus } from '../model/component-status';
import { Observable } from 'rxjs/Rx';



@Injectable()
export class ManageComponentStatusService {
    @Output() OnChange: EventEmitter<any> = new EventEmitter();
    @Output() ManageHeader: EventEmitter<any> = new EventEmitter();

    componentStatus: any;

    constructor() {
        this.componentStatus = new ComponentStatus();
        this.componentStatus.header = false;
        this.componentStatus.leftMenu = false;
        this.componentStatus.rightMenu = false;
        this.componentStatus.plainHeader = true;
    }

    public setComponentStatus(header: any, left: any, right: any) {

        this.componentStatus.header = header;
        this.componentStatus.leftMenu = left;
        this.componentStatus.rightMenu = right;
        this.OnChange.emit(this.componentStatus);
    }

    public getComponentStatus(): Observable<any> {
        return this.OnChange;
    }

    public setPlainHeader(status:any) {

        this.componentStatus.plainHeader = status;
        var self = this;
        setTimeout(function () {
            self.ManageHeader.emit(self.componentStatus.plainHeader);
        }, 300);


    }

    public restoreHeader() {
        this.componentStatus.plainHeader = true;
    }

    public getHeaderStatus(): Observable<any>{
        return this.ManageHeader;
    }

}

在 app.component.ts 中,我们设置了组件值,还有一个订阅来检查更改

 export class AppComponent implements OnInit {

    title = 'test App';
    authSettings: any;
    appConstants: any;
    _router: any;
    header: any=false;
    leftmenu: any=false;
    rightmenu: any=false;
    compModel: any;


    constructor(private ngAuthService: NgAuthService, private tenantServ: TenantService,
        private loadingBarService: LoadingBarService, private router: Router,
        public manageComp: ManageComponentStatusService,public socialServ: SocialMediaSettingsService) {

        this._router = router;        
        this.authSettings = ngAuthService.getNgAuth();
        this.appConstants = ngAuthService.getAppConstant();
        //this.manageComp.setComponentStatus(false, false, false);


        router.events.subscribe(event => {
            if (event instanceof NavigationStart) {
                this.loadingBarService.start();
                //console.log("navigation start");
            }
            else if (event instanceof NavigationEnd) {

                //console.log("navigation end");
                this.loadingBarService.complete();
            }


        });

        this.compModel = this.manageComp.getComponentStatus();

    }


    logOut() {
        this.manageComp.setComponentStatus(false, false, false);
        this._router.navigate(['login']);

    }

    ngOnInit() {

        //this.header = this.compModel.header;
        //this.leftmenu = this.compModel.leftMenu;
        //this.rightmenu = this.compModel.rightMenu;
        this._router.navigate(['login']);
        /*subscribing to change*/
        this.manageComp.getComponentStatus().subscribe(
            data => {
                this.header = data.header;
                this.leftmenu = data.leftMenu;
                this.rightmenu = data.rightMenu;
            });



    }
    ngOnChanges() {
        alert("change detected");
    }



}

登录成功后加载的路由是abc 下面是 abc 组件。我只添加相关部分

ngOnInit() {

        this.compStatus.setComponentStatus(true, true, true);//UPDATING HERE
        this.userServ.setUserProfile();
        this.compStatus.setPlainHeader(true);
        this.opts = {
            barBackground: '#C9C9C9',
            gridBackground: '#D9D9D9',
            barBorderRadius: '1',
            barWidth: '2',
            gridWidth: '1'
        };
        this.socialMediaData = this.socialSetServ.getSocialProvider();
        this.isContentEditable = this.commonServ.getAppConfig().contentEditable;        

    }

当登录页面加载时,出现此异常。

ng:///AppModule/AppComponent.ngfactory.js:40 ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'undefined'. Current value: 'false'.

我知道我与删除更改有关,但不知道如何更正。

This error happens because the value of the variable changed before change Detection can work on the previous one.

A work around for this is to use The setTimeout function schedules a macrotask then will be executed in the following VM turn.

你可以把这段代码 this.compStatus.setComponentStatus(true, true, true); 放在 set Timeout

里面
setTimeout(() => {
    this.compStatus.setComponentStatus(true, true, true);
}, 0);