angular2属性已更改错误

angular2属性已更改错误,angular,Angular,我有一个指令app.service.ts,用于存储应用程序状态数据,我正尝试从其他组件使用该指令,以便获取和设置应用程序的状态(正在工作) 但是,当我尝试将此指令中的属性绑定到视图时,它会出现此错误 异常:表达式“正在加载:{{loadState}}inApp@0:23'在检查后已更改。上一个值:“false”。[loading:{{loadState}}中的当前值:“true”App@0:23] 这里我试图显示正在加载的文本,此时appState.get().loadState==true 应

我有一个指令
app.service.ts
,用于存储应用程序状态数据,我正尝试从其他组件使用该指令,以便获取和设置应用程序的状态(正在工作)

但是,当我尝试将此指令中的属性绑定到视图时,它会出现此错误

异常:表达式“正在加载:{{loadState}}inApp@0:23'在检查后已更改。上一个值:“false”。[loading:{{loadState}}中的当前值:“true”App@0:23]

这里我试图显示正在加载的文本,此时
appState.get().loadState==true

应用程序服务.ts-

应用程序ts

import {AppState} from './app.service';

export class App{

   constructor(public appState: AppState) {
      this.appState.set('loadState', false);
   }
   get loadState() { 
      return this.appState.get().loadState;
   }
}
 export class HomeCmp {
 page;

 constructor(private wp: WPModels, private appState: AppState) {}

 ngOnInit() {
   var pageId = this.appState.get().config.home_id;
   this.appState.set('loadState', true);    // before http request

   this.wp.fetch(WPEnpoint.Pages, pageId).subscribe(
     res => {
       this.page = res;
       this.appState.set('loadState', false);  // after http request
     },
     err => console.log(err)
   );
 }
}
export class HomeCmp {
 page;

 constructor(private wp: WPModels, private appState: AppState) {}

 ngOnInit() {
   var pageId = this.appState.get().config.home_id;
   this.appState.set('loadState', true);    // before http request

   this.wp.fetch(WPEnpoint.Pages, pageId).subscribe(
     res => {
       this.page = res;
       this.appState.set('loadState', false);  // after http request
     },
     err => console.log(err)
   );
 }
}
export class HomeCmp {
 page;

 constructor(private wp: WPModels, private service: AppStateService) {}

 ngOnInit() {
   this.service.updateState(true);    // before http request

   this.wp.fetch(WPEnpoint.Pages, pageId).subscribe(
     res => {
       this.page = res;
       this.service.updateState(false);  // after http request
     },
     err => console.log(err)
   );
 }
}
app.html

<div class="app-inner">
  <p>loading: {{loadState}}</p>
    <header></header>
  <main layout="column" layout-fill>
    <router-outlet></router-outlet>
  </main>
</div>

我认为您可以利用ChangeDetectorRef类及其方法detectChanges

为此,将其注入应用程序组件,并在其ngAfterViewInit中调用该方法

 constructor(private cdr: ChangeDetectorRef) {}

  ngAfterViewInit() {
      this.cdr.detectChanges();
  }
有关更多详细信息,请参见此问题:

也就是说,我将在您的状态服务中使用一个可观察属性,以便在读取时通知组件

@Injectable()
export class AppStateService {
  state: string;
  state$: Observable<string>;
  private stateObserver : Observer<string>;

  constructor(){
    this.state$ = new Observable(observer => this.stateObserver = observer).share();
  }

  updateState(newState) {
    this.state = newState;
    this.stateObserver.next(newState);
  }
}
有关更多详细信息,请参阅以下链接:

这是开发模式的一个特性,可以按预期工作。调用enableProdMode()-请参阅何时引导应用程序以防止引发异常


您需要再次触发更改检测

wp
似乎以某种方式在Angulars区域之外运行代码。要强制代码返回到Angulars区域,请使用
zone.run()
,如下所示。对于更新属性的代码,您的视图绑定到:

从'angular2/core'导入{NgZone};
导出类HomeCmp{
页
构造函数(私有区域:NgZone,私有wp:WPModels,私有appState:appState){}
恩戈尼尼特(){
var pageId=this.appState.get().config.home\u id;
this.appState.set('loadState',true);//在http请求之前
this.wp.fetch(WPEnpoint.Pages,pageId).subscribe(
res=>{
此.zone.run(()=>{
this.page=res;
this.appState.set('loadState',false);//在http请求之后
});
},
err=>console.log(err)
);
}
}

解决方案非常简单,通过制作一个特殊组件来显示state service
app.service.ts
中的加载状态,下面是代码:

LoaderCmp直接显示appState服务中的
loadState
属性

import {Component} from 'angular2/core';
import {AppState} from "../../app.service";

@Component({
  selector: 'loader',
  template: `
   loading state : {{appState._state.loadState}}
  `
})

export class LoaderCmp{
  constructor(private appState: AppState) {}
}
import {Component} from 'angular2/core';
import {AppStateService} from "../../app.state";

@Component({
  selector: 'loader',
  template: `
   loading state : {{ active }}
  `
})

export class LoaderCmp{
  active;
  constructor(private service: AppStateService) {}
    ngOnInit() {
       this.service.state$.subscribe(newState => {
       this.active = newState;
    });
  }
}
app.service.ts保存我们的应用程序状态

import {Injectable} from 'angular2/core';
import {WebpackState} from 'angular2-hmr';

@Injectable()
export class AppState {
  _state = {}; // you must set the initial value
  constructor(webpackState: WebpackState) {
    this._state = webpackState.select('AppState', () => this._state);
  }

  get(prop?: any) {
    return this._state[prop] || this._state;
  }

  set(prop: string, value: any) {
    return this._state[prop] = value;
  }
}
app.ts无需配置,只需将
LoaderCmp
添加到应用程序指令中即可

@Component({
  selector: 'app',
  directives: [HeaderCmp, LoaderCmp],
  template: `
  <div class="app-inner">
    <loader></loader>
    <header></header>
    <main>
      <router-outlet></router-outlet>
    </main>
  </div>
  `
})
export class App  {
    constructor() { }
}
@Component({
  selector: 'app',
  directives: [HeaderCmp, LoaderCmp],
  template: `
  <div class="app-inner">
    <loader></loader>
    <header></header>
    <main>
      <router-outlet></router-outlet>
    </main>
  </div>
  `
})
export class App  {
    constructor() { }
}

另一个解决方案是使用observable和share函数,这里我们将
app.service.ts
更改为
app.state.ts
,它只支持一个属性

LoaderCmp直接显示appState服务中的
loadState
属性

import {Component} from 'angular2/core';
import {AppState} from "../../app.service";

@Component({
  selector: 'loader',
  template: `
   loading state : {{appState._state.loadState}}
  `
})

export class LoaderCmp{
  constructor(private appState: AppState) {}
}
import {Component} from 'angular2/core';
import {AppStateService} from "../../app.state";

@Component({
  selector: 'loader',
  template: `
   loading state : {{ active }}
  `
})

export class LoaderCmp{
  active;
  constructor(private service: AppStateService) {}
    ngOnInit() {
       this.service.state$.subscribe(newState => {
       this.active = newState;
    });
  }
}
app.state.ts保存我们的加载状态

import "rxjs/add/operator/share";
import {Observable} from "rxjs/Observable";
import {Observer} from "rxjs/Observer";
import {Injectable} from "angular2/core";

@Injectable()
export class AppStateService {
  state: boolean = false;
  state$: Observable<boolean>;
  private stateObserver : Observer<boolean>;

  constructor(){
    this.state$ = new Observable(observer => this.stateObserver = observer).share();
  }

  updateState(newState) {
      this.state = newState;
      this.stateObserver.next(newState);
  }
}
从任何组件更新应用程序状态,例如:home.ts

import {AppState} from './app.service';

export class App{

   constructor(public appState: AppState) {
      this.appState.set('loadState', false);
   }
   get loadState() { 
      return this.appState.get().loadState;
   }
}
 export class HomeCmp {
 page;

 constructor(private wp: WPModels, private appState: AppState) {}

 ngOnInit() {
   var pageId = this.appState.get().config.home_id;
   this.appState.set('loadState', true);    // before http request

   this.wp.fetch(WPEnpoint.Pages, pageId).subscribe(
     res => {
       this.page = res;
       this.appState.set('loadState', false);  // after http request
     },
     err => console.log(err)
   );
 }
}
export class HomeCmp {
 page;

 constructor(private wp: WPModels, private appState: AppState) {}

 ngOnInit() {
   var pageId = this.appState.get().config.home_id;
   this.appState.set('loadState', true);    // before http request

   this.wp.fetch(WPEnpoint.Pages, pageId).subscribe(
     res => {
       this.page = res;
       this.appState.set('loadState', false);  // after http request
     },
     err => console.log(err)
   );
 }
}
export class HomeCmp {
 page;

 constructor(private wp: WPModels, private service: AppStateService) {}

 ngOnInit() {
   this.service.updateState(true);    // before http request

   this.wp.fetch(WPEnpoint.Pages, pageId).subscribe(
     res => {
       this.page = res;
       this.service.updateState(false);  // after http request
     },
     err => console.log(err)
   );
 }
}

您可以为此使用共享对象。我认为HTML中的
{{loadState}}
总是以这种方式抛出错误。而是尝试绑定服务中使用的一些共享变量。例如,_state={}是一个共享对象。为它设置一些属性,然后在html中,您可以通过
{{appState.\u state.someProperty}}
@micronyks相同的错误我尝试了这个,但它给我的错误完全相同您的意思是您尝试调用
检测更改
?在哪个组件生命周期钩子中?否则,我在我的代码片段中输入了一个错误。取而代之的是
ngAfterViewInit
…似乎不需要
detectChanges
,我喜欢在状态服务中使用observable的想法。但是我选择了普通的app.service.ts,因为它支持多个属性。我写了两种方法的解决方案。