I created an Angular issue: https://github.com/angular/angular/issues/20471
Also started a proposal in gist: https://gist.github.com/matthewharwood/23ea18c8509b8056813d3c3e7df0d1b2
Hey I was messing with the
Angular/cdk directive which works outside of ngZones
and @angular/animations
. I was wonder if you could tell me if a particular layout thrashing optimization is taken into account? My secret weapon for performance has always been to use fastdom
library for effects like parallax scrolling. I've yet to test perf because I have a feeling that angular already has methods similar too fastdom, that I just don't know about.
Question: Does Angular have any method for scheduling measures and mutates of the DOM? If so, how? If not, would it be wise to implement fastdom into libraries like cdk and animations, if so again, could you give me some examples to help me communicate this better to the angular team?
Anyways describing the problem is a bit hard to explain; however, lets look at the fastdom and I'll move to angular afterwards.
Fastdom works like this:
fastdom.measure(() => {
console.log('measure');
});
fastdom.mutate(() => {
console.log('mutate');
});
fastdom.measure(() => {
console.log('measure');
});
fastdom.mutate(() => {
console.log('mutate');
});
Would output:
measure
measure
mutate
mutate
When looking at cdk: https://sourcegraph.com/github.com/angular/material2@master/-/blob/src/cdk/scrolling/scrollable.ts
doesn't seem to have kind of measure wrapper unless ngZones is it.
ngOnInit() {
this._scrollListener = this._ngZone.runOutsideAngular(() => {
return this._renderer.listen(this.getElementRef().nativeElement, 'scroll', (event: Event) => {
this._elementScrolled.next(event);
});
});
this._scroll.register(this);
}
Test case: Imagine you had a element on a page that would translate based on the current scroll position.
You could implement this in something like: (Pseudo code)
// index.html
<body [cdkScrollable]>
<some-component></some-component>
</body>
// some-component.ts
@Component({
selector: 'some-component'
})
export class SomeComponent implement OnInit, AfterViewInit {
@ViewChild(CdkScrollable) child: cdkScrollable;
private _el: any;
constructor(private _elementRef: ElementRef, private _renderer: Renderer2){}
ngOnInit() {
this._el = this._renderer.selectRootElement(this._elementRef);
}
ngAfterViewInit() {
this._makeAnimation()
}
private _makeAnimation() {
// first build the animation
const myAnimation = this._builder.build([
style({ top: 0 }),
animate(1000, style({ top: `${cdkScrollable. elementScrolled(). scrollTop + 100}px` }))
]);
// then create a player from it
const player = myAnimation.create(this._el.nativeElement);
player.play();
}
}
Over something like this if you used fast dom:
// this should need optimization to run outside of angular too.
@Component({
selector: 'some-other-component'
})
export class SomeOtherComponent {
private _el: any;
constructor(private _elementRef: ElementRef, private _renderer: Renderer2){}
public ngOnInit() {
this._el = this._renderer.selectRootElement(this._elementRef);
this.renderLoop_();
}
private renderLoop_() {
this.renderScrollBar_();
fd.measure(() => this.renderLoop_());
}
private renderScrollBar() {
fd.measure(() => {
const scroll = window.scrollY + 100;
fd.mutate(() => {
this._el.top = `${scroll}px`;
});
});
}
}
I'm pretty certain that this kind of optimization isn't included unless this._ngZone.runOutsideAngular
is that optimization. Does anyone have any insight into the presence of optimization?