dom更改时Angular2 setinterval被阻止

Posted

技术标签:

【中文标题】dom更改时Angular2 setinterval被阻止【英文标题】:Angular2 setinterval blocked while dom changes 【发布时间】:2018-06-18 13:39:39 【问题描述】:

我有一个基本的 javascript/JQuery 应用程序,我现在正在迁移到 Angular2,我的 UI 使用 material.angular.io。

在旧版本中,当我使用“setInterval(func,200);”时每 200 毫秒查询一次服务器,每 200 毫秒调用一次,即使在使用 JQuery 的 append(content) 或 html(content) 函数添加 DOM 元素时也是如此。

现在在 Angular2 中,虽然 DOM 使用 *ngFor 进行了更改并且更改很大(从服务器获取约 200 行并将它们显示为带有诸如切换按钮之类的 Material 组件的表格行),但一切都冻结了大约 1 秒钟。服务器的日志向我显示,呼叫确实停止了大约 1 秒钟,然后每 200 毫秒再次恢复。 但是当我以较小的组添加 DOM 元素(即:每 200 毫秒 10 个项目)时,一切都很好。

当我使用 F11 切换全屏时,当浏览器重绘布局以匹配新窗口大小时,也会发生这种情况。

使用 Chrome 的调试控制台,我可以看到“Timer Fired(zone.js:2087)”显示“Recurring handler takes 731.18 ms”警告。我不确定问题是因为我的代码还是因为它是一个 material.io 问题,但我认为 Angular 的 setInterval 与普通的 JavaScript setInterval 不同?

以下是相关代码:

<tbody>
  <tr *ngFor="let io of inputs; trackBy: trackByFn">
    <td>io.id</td>
    <td>io.name</td>
    <td>io.description</td>
    <td><mat-slide-toggle>Test</mat-slide-toggle></td>
    <td>io.device</td>
  </tr>
</tbody>

来自服务器的日志显示上次查询的时间:

15:40:25.229 stat.service.ts:108 200
15:40:25.430 stat.service.ts:108 201
15:40:25.630 stat.service.ts:108 201
15:40:25.831 stat.service.ts:108 201
15:40:26.031 stat.service.ts:108 200
15:40:26.235 stat.service.ts:108 203
15:40:26.435 stat.service.ts:108 201
15:40:26.636 stat.service.ts:108 201
15:40:26.838 stat.service.ts:108 202
15:40:27.039 stat.service.ts:108 201
15:40:27.895 stat.service.ts:108 856 // WHEN THE COMPONENT LOADS
15:40:28.200 stat.service.ts:108 305
15:40:28.442 stat.service.ts:108 242
15:40:28.679 stat.service.ts:108 237
15:40:28.901 stat.service.ts:108 221
15:40:29.131 stat.service.ts:108 231
15:40:29.363 stat.service.ts:108 231

【问题讨论】:

每 200 毫秒调用一次 - 这不太可能。如果主线程被阻塞,则它被阻塞。该案例并非特定于 Angular(它没有自己的 setInterval,只有 Zone.js 修补的那个),而是针对任何阻塞的 JS 代码。尝试 setInterval 和 for 大循环,你会看到。 【参考方案1】:

也许这是 Angular 中 ChangeDetection 的问题。当您更改对象时,它会重新渲染整个事物。尝试在您的组件中实现 ChangeDetectionStrategy 并查看是否有任何改进。您的组件代码将如下所示:

@Component(
  selector: "your-comp",
  templateUrl: "./your.component.html",
  changeDetection: ChangeDetectionStrategy.OnPush
)
export class YourComponent
  constructor(private cdr: ChangeDetectorRef) 

 // this.cdr.markForCheck(); use code for change on DOM when you get data in observable

希望对你有帮助

【讨论】:

没有。正如我所说,当我单击 F11 切换全屏时也会发生这种情况,并且仅在修改 DOM 时才会发生。当设置了 DOM 并且只有数据更改时,绑定可以正常工作,没有任何问题。只是最初的 DOM 修改需要时间。 200 行数据并不多,我渲染了大约 10000 行具有 7 个属性的数据,但从未发现任何问题。你应该深入研究它来解决这个问题。可能这在未来会让人头疼。

以上是关于dom更改时Angular2 setinterval被阻止的主要内容,如果未能解决你的问题,请参考以下文章

Angular2 指令:如何检测 DOM 更改

Angular2 指令监听父组件回调或更改

dom完成渲染后Angular2执行操作

输入更改时的Angular2调用函数

由 DOM 属性 _ngcontent-* 与 _nghost-* 引起的 Angular2 样式问题

Angular2:变量更改时视图不更新