In an application that uses ng-upgrade to use some new ng2 (V2.2.4) components inside a big ng1 (V1.5.9) app (using ui-router) I am currently seeing a very strange change-detection issue. As far as I can tell, this has been introduced in some upgrade of ng2, but sadly I can't easily verify that currently.
在一个使用ng-upgrade来在一个大的ng1 (V1.5.9)应用(使用ui-router)中使用一些新的ng2 (V2.2.4)组件的应用程序中(使用ui-router),我目前看到了一个非常奇怪的变化检测问题。据我所知,这是在ng2的一些升级中引入的,但遗憾的是目前我还不能很容易地验证。
I have reduced it to a minimal example by now where i simply have this component:
到目前为止,我已经将它简化为一个最小的示例,其中只有以下几个部分:
@Component({
selector:'my-ng2-demo',
template: '<div>{{status}}</div>'
})
export class MyNg2Demo implements OnDestroy {
public status:boolean = true;
private interval:any;
constructor() {
this.interval = setInterval(() => {
this.status = !this.status;
console.log('status: ' + this.status);
}, 2000);
}
ngOnDestroy():void {
clearInterval(this.interval);
}
}
That component is upgraded in the upgrade-adapter and registered as an entry-component in the module.
该组件在升级适配器中升级,并作为模块中的入口组件注册。
The component is used in the template of an ng1 controller like this:
该组件用于ng1控制器的模板中,如下所示:
<my-ng2-demo></my-ng2-demo>
When I open a browser and navigate directly to that page (the route of the ng1 controller) everything works as expected: the ui shows true/false alternating every 2 seconds.
当我打开浏览器并直接导航到那个页面(ng1控制器的路由)时,一切都按预期运行:ui每2秒显示一次真/假交替。
However: when I navigate away & then come back to the page (visiting some different routes) then suddenly change detection doesn't seem to work. The displayed value alternates only about every 5-6 seconds, seems quite random, although in the console I still see the expected values.
然而,当我离开,然后回到页面(访问一些不同的路线),然后突然改变检测似乎不工作。显示的值大约每5-6秒变化一次,看起来很随机,尽管在控制台中我仍然可以看到预期的值。
When I change the component's constructor to this:
当我将组件的构造函数改为:
constructor(private zone: NgZone) {
this.interval = setInterval(() => {
zone.run(() => {
this.status = !this.status;
console.log('status: ' + this.status);
});
}, 2000);
}
It suddenly works again.
它突然再次工作。
Obviously this isn't a feasible solution since the behavior I'm seeing in the real app is much more complex (i would have to add zone.run
in dozens of places probably, which would not be maintainable).
显然,这不是一个可行的解决方案,因为我在实际应用程序中看到的行为要复杂得多(我可能需要添加zone.run在几十个地方,这可能是不可维护的)。
I have debugged this for hours and don't understand what is happening. In Chrome's JavaScript profiler, I basically see that the page idles for almost the whole time in those 5-6 seconds where nothing happens.
我已经调试了好几个小时,不知道发生了什么。在Chrome的JavaScript剖析器中,我基本上看到页面在5-6秒内几乎一直处于闲置状态。
This is not a screenshot from that demo-component (but it basically looks the same) but from profiling the tab-component I was initially testing (tab-switching took just as long with no visible actions in between).
这不是来自于demo组件的屏幕截图(但基本上看起来是一样的),但是从对表组件的分析开始,我最初是在测试(在中间没有可见的操作时,tab切换的时间也一样长)。
update:
更新:
After a bit more experimentation what I find quite surprising also is that when instead of putting the status-changing code into a zone.run
call, I add a call to ApplicationRef.tick()
(as mentioned here for example: https://*.com/a/34829089/1335619 ) it also does NOT work at all. I don't understand why forcing a complete application-change-detection does nothing, but a zone-run call somehow works.
在进行了更多的实验之后,我发现相当令人惊讶的是,当我没有将更改状态的代码放入zone.run调用时,我向ApplicationRef.tick()添加了一个调用(如这里提到的:https://*.com/a/3482909 /1335619),它也完全不起作用。我不明白为什么强制执行一个完整的应用程序更改检测什么也不做,但是分区运行调用以某种方式工作。
Example code with tick call which does not work:
带有勾号调用的示例代码不起作用:
constructor(private applicationRef:ApplicationRef) {
this.interval = setInterval(() => {
this.status = !this.status;
console.log('status: ' + this.status);
applicationRef.tick();
}, 2000);
}
1 个解决方案
#1
3
There is a bug in the Angular version you are using. Change detection does not work as it should in ng-upgraded apps.
在你使用的角度版本中有一个错误。在ng升级的应用程序中,更改检测并不适用。
Please refer to https://github.com/angular/angular/issues/12318 for further details.
详情请参阅https://github.com/angular/angular/issues/12318。
If you upgrade to 2.4.4, it should resolve the issue.
如果您升级到2.4.4,它应该会解决这个问题。
#1
3
There is a bug in the Angular version you are using. Change detection does not work as it should in ng-upgraded apps.
在你使用的角度版本中有一个错误。在ng升级的应用程序中,更改检测并不适用。
Please refer to https://github.com/angular/angular/issues/12318 for further details.
详情请参阅https://github.com/angular/angular/issues/12318。
If you upgrade to 2.4.4, it should resolve the issue.
如果您升级到2.4.4,它应该会解决这个问题。