change-detection-tree
change-detection-tree copied to clipboard
Visual detecting changes in the component tree (View Engine)
Visual detecting changes in the component tree
This project shows you how the component tree in Angular is updated. The time shown on the component nodes in the tree is the interval between ngDoCheck and ngAfterViewChecked.
$ git clone https://github.com/Angular-RU/change-detection-tree cd-tree && cd cd-tree
$ npm install # install all dependencies
$ ng serve # worked with jit or aot
StackBlitz examples
✅ ChangeDetection.Default + NgZone (static tree + projection):
Example: https://stackblitz.com/github/Angular-RU/change-detection-tree
Learn more
$ ng serve --app 0 --port 4200
✅ ChangeDetection.OnPush + NgZone (random generate tree):
Example: https://stackblitz.com/github/Angular-RU/change-detection-tree/tree/onpush
Learn more
$ ng serve --app 1 --port 4201
✅ ChangeDetection.OnPush + Async pipe - without ngZone (random generate tree):
Example: https://stackblitz.com/github/Angular-RU/change-detection-tree/tree/onpush-async-without-zone
Learn more
$ ng serve --app 2 --port 4202
✅ ChangeDetection.Default + Async pipe + ngZone (random generate tree):
Example: https://stackblitz.com/github/Angular-RU/change-detection-tree/tree/async-pipe
Learn more
$ ng serve --app 3 --port 4203
TODO
❌ ChangeDetection.Default + Async pipe + Reactive Forms - without ngZone:
Example: In progress
❌ Custom state-management (services):
Example: In progress
❌ NgRx:
Example: In progress
❌ MobX:
Example: In progress
❌ Web-worker platform:
Example: In progress
Checklist for detect problem
- Detect problem with Zone
Copy the code and paste it into the console. If your component tree too often calls Application.tick() your application will disappear.
let [root] = getAllAngularRootElements();
let appRoot = ng.probe(root);
let [rootComponent] = appRoot.injector.get(ng.coreTokens.ApplicationRef).components;
let ChangeDetectorRef = rootComponent.changeDetectorRef.constructor.prototype;
ChangeDetectorRef.constructor.prototype.detectChanges = (function () {
let oldDC = ChangeDetectorRef.constructor.prototype.detectChanges;
let map = new WeakMap();
return function () {
Zone.root.run(() => showChangeDetection(this));
return oldDC.apply(this, arguments);
}
function showChangeDetection (changeDetector) {
let view = changeDetector._view;
modifyNodeOpacity(view, fade);
modifyNodeOpacity(view, (node) => {
let timeout = map.get(node.renderElement);
if (timeout) {
clearTimeout(timeout);
}
timeout = setTimeout(() => show(node), 1000);
map.set(node.renderElement, timeout);
});
}
function modifyNodeOpacity (view, modifier) {
view.nodes.forEach(node => {
if (node && node.renderElement && node.renderElement.style) {
modifier(node);
}
});
}
function fade (node) {
let { style } = node.renderElement;
let opacity = parseFloat(style.opacity) || 1;
let newOpacity = opacity - 0.01;
style.display = 'block';
style.opacity = newOpacity > 0 ? newOpacity : 0;
}
function show (node) {
let { style } = node.renderElement;
style.display = 'block';
style.opacity = 1;
}
})();