问题出现的场景:
可能是项目存在已久代码已不知所云、或者是陷入某个回调函数中、又或是使用了某个插件后。
先看下angular的变更检测策略:
Default :ng提供的Default的检测策略,只要组件的input发生改变,就触发检测;
OnPush :OnPush检测策略是input发生改变,并不立即触发检测,而是输入的引用发生变化时,才会触发检测。
ChangeDetectorRef.detectChanges():可显式的控制变更检测,在需要的地方使用即可;
NgZone.run():在整个应用中进行变更检测
ApplicationRef.tick():在整个应用中进行变更检测,侦听NgZone的onTurnDone事件,来触发检测
这个时候你就可以使用以下几种方法解决
1、查看组件中元数据中是否使用了
changeDetection: ChangeDetectionStrategy.OnPush
如果有,则说明该组件不使用变化检测,组件内所有数据变化都不会更新到视图
可以根据需求删除这句话或者在更新的数据后面加
this.changeDetectorRef.markForCheck();
如果不想每个更新数据的位置都加这句话那就删掉OnPush
若是还不好使,就看第二种方式
2、如果压根元数据中就没有使用OnPush(推荐方法)
可以使用如下代码来解决
constructor( private changeDetectorRef: ChangeDetectorRef, ) {}在数据变化后不起作用的地方加上
this.changeDetectorRef.detectChanges();这样既可手动触发数据监测了
3、ngZone.run() 方法会导致整个应用程序发生更改检测(非必要不推荐使用)
constructor( private ngZone: NgZone ) {}我们可以将某个要发生改变的变量或者方法直接放到ngZong.run()中。比如:
this.ngZone.run(()=>{this.closeNum()}) this.ngZone.run(()=>{this.uploadProgress})
如果在Angulars区域外运行的某些代码调用Angulars代码并更改状态,则需要明确调用更改检测,因为Angular无法知道状态发生了变化.
如果对状态的更改是组件的本地(例如组件字段),则ChangeDetectorRef.detectChanges或ChangeDetectorRef.markforCheck更有效.
如果来自外部的呼叫例如导航到不同的路由,这可能会对许多组件产生影响,并且还不清楚整个路由更改何时完成,因为它可能导致异步调用(以及调用回调).在这种情况下,zone.run()是更好的选项,因为直接和间接调用的代码(如observable和promises的回调)将在Angulars区域内运行,Angular将识别它们并自动调用更改检测
发表评论: