调试Angular2更改检测器

时间:2016-11-28 18:07:29

标签: angular

我希望深入了解变更检测器在我们的应用程序中如何运行的细节。最近我发现我们的应用程序远远超出了我们的需要,并提交了Angular issue。我已经能够修复我所知道的所有地方,但是现在我希望有一个简单的方法来确切地知道变化探测器何时运行,为什么它在运行,以及哪些组件是脏的什么时候运行获取此信息的最佳和最简单方法是什么?

更新:因此您可以在AppView.detectChanges中设置一个断点,以便在更改检测器运行时断开,然后逐步执行该代码,您可以看到正在检查的内容。但是,我仍然不确定如何轻松确定触发更改检测器的内容或者标记要检查的组件的人员。

3 个答案:

答案 0 :(得分:3)

另一种方法是创建自定义装饰器以添加ngDoCheck钩子并将其记录到页面中的组件,这样做的缺点是您必须将此装饰器添加到页面中的每个组件:< / p>

(window as any).calls = {};
export function debug() {
    return (constructor: any) => {
        if (!constructor.prototype.ngDoCheck) {
            constructor.prototype.ngDoCheck = () => {
                console.log("ngDoCheck", constructor.name);
                const calls = (window as any).calls;
                calls[constructor.name] = calls[constructor.name] ? calls[constructor.name] + 1 : 1;
            };
        }
    };
}
(window as any).resetCalls = () => (window as any).calls = {};

您可以在控制台中查看calls,了解最常被调用的组件的统计信息。 请记住,ngDoCheck调用并不意味着对该组件运行更改检测,它表明更改检测正在父组件上运行。

尚不确定如何一致地确定实际触发变更检测的内容。有些想法会覆盖ngZoneChangeDetector来记录实际触发器。

答案 1 :(得分:3)

注意:这是打开的:“什么触发变化检测器?”

我花了一些时间研究主题,但是我得出的结论是,不修改角度源代码就很难做到这一点。但是,我可以分享一些解决此问题的技巧。

  1. 我试图找出是什么事件(或任何其他异步任务)触发了根组件(ApplicationRef.prototype.tick)上的更改检测。
  2. 我在core.js文件的ApplicationRef.prototype.tick上创建一个断点。

enter image description here

  1. 停止时,我会寻找onIvokeTask方法调用。

enter image description here

  1. 这是棘手的部分-此处的操作取决于操作类型(dom事件,超时,promise解析)和angular的版本。但是通常,我会在当前范围内寻找task变量。此变量存储有关触发更改检测的操作的信息。对于某些事件(setTimeout),callback属性将与我传递给setTimeout的回调完全相同,但例如click事件,它也会回调,但由一些有角装饰器包装。但是,您可以通过eventNametarget之类的其他属性来确定操作。

enter image description here

  1. 所以,我发现的任务是变更检测器触发的原因。

是的,我知道这太复杂了,但是我不知道更好的解决方案。如果有人可以做得更好,请分享! :)

答案 2 :(得分:0)

尽管调试本身仍然是一个遥不可及的目标,但是practical demoaccompanying article至少可以更好地理解这一切的原理。

编辑:另请参见10 Things Every Angular Developer Should Know About Zone.js