知向前端
angular回掉函数里数据修改视图不更新的问题解决
2019-10-6 Jon
做angular项目中有时会遇到组件中的数据变化后视图中没有更新的问题

问题出现的场景:

可能是项目存在已久代码已不知所云、或者是陷入某个回调函数中、又或是使用了某个插件后。



先看下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将识别它们并自动调用更改检测
发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容