Skip to content

Commit 57a2f29

Browse files
crisbetotinayuangao
authored andcommitted
perf(sidenav): avoid recalculating the inline styles while sidenav is open (#6189)
* Avoids recalculating the sidenav inline styles for every change detection cycle while the sidenav is open by doing it only when an animation starts. * Removes a few one-liner methods that were being used in one place.
1 parent fa3cf12 commit 57a2f29

File tree

3 files changed

+24
-41
lines changed

3 files changed

+24
-41
lines changed

src/lib/sidenav/sidenav-container.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33

44
<ng-content select="md-sidenav, mat-sidenav"></ng-content>
55

6-
<div class="mat-sidenav-content" [ngStyle]="_getStyles()" cdk-scrollable>
6+
<div class="mat-sidenav-content" [ngStyle]="_styles" cdk-scrollable>
77
<ng-content></ng-content>
88
</div>

src/lib/sidenav/sidenav.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ describe('MdSidenavContainer', () => {
350350

351351
const contentElement = fixture.debugElement.nativeElement.querySelector('.mat-sidenav-content');
352352

353-
expect(parseInt(contentElement.style.marginLeft)).toBe(0);
353+
expect(parseInt(contentElement.style.marginLeft)).toBeFalsy();
354354

355355
fixture.componentInstance.showSidenav = true;
356356
fixture.detectChanges();

src/lib/sidenav/sidenav.ts

Lines changed: 22 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,9 @@ export class MdSidenavContainer implements AfterContentInit {
326326
private _left: MdSidenav | null;
327327
private _right: MdSidenav | null;
328328

329+
/** Inline styles to be applied to the container. */
330+
_styles: { marginLeft: string; marginRight: string; transform: string; };
331+
329332
constructor(@Optional() private _dir: Directionality, private _element: ElementRef,
330333
private _renderer: Renderer2, private _ngZone: NgZone,
331334
private _changeDetectorRef: ChangeDetectorRef) {
@@ -362,13 +365,13 @@ export class MdSidenavContainer implements AfterContentInit {
362365
* is properly hidden.
363366
*/
364367
private _watchSidenavToggle(sidenav: MdSidenav): void {
365-
takeUntil.call(sidenav._animationStarted, this._sidenavs.changes)
366-
.subscribe(() => {
367-
// Set the transition class on the container so that the animations occur. This should not
368-
// be set initially because animations should only be triggered via a change in state.
369-
this._renderer.addClass(this._element.nativeElement, 'mat-sidenav-transition');
370-
this._changeDetectorRef.markForCheck();
371-
});
368+
takeUntil.call(sidenav._animationStarted, this._sidenavs.changes).subscribe(() => {
369+
// Set the transition class on the container so that the animations occur. This should not
370+
// be set initially because animations should only be triggered via a change in state.
371+
this._renderer.addClass(this._element.nativeElement, 'mat-sidenav-transition');
372+
this._updateStyles();
373+
this._changeDetectorRef.markForCheck();
374+
});
372375

373376
if (sidenav.mode !== 'side') {
374377
takeUntil.call(merge(sidenav.onOpen, sidenav.onClose), this._sidenavs.changes).subscribe(() =>
@@ -461,40 +464,20 @@ export class MdSidenavContainer implements AfterContentInit {
461464
return (this._isSidenavOpen(sidenav) && sidenav.mode == mode) ? sidenav._width : 0;
462465
}
463466

464-
_getMarginLeft() {
465-
return this._left ? this._getSidenavEffectiveWidth(this._left, 'side') : 0;
466-
}
467-
468-
_getMarginRight() {
469-
return this._right ? this._getSidenavEffectiveWidth(this._right, 'side') : 0;
470-
}
471-
472-
_getPositionLeft() {
473-
return this._left ? this._getSidenavEffectiveWidth(this._left, 'push') : 0;
474-
}
475-
476-
_getPositionRight() {
477-
return this._right ? this._getSidenavEffectiveWidth(this._right, 'push') : 0;
478-
}
479-
480-
/**
481-
* Returns the horizontal offset for the content area. There should never be a value for both
482-
* left and right, so by subtracting the right value from the left value, we should always get
483-
* the appropriate offset.
484-
*/
485-
_getPositionOffset() {
486-
return this._getPositionLeft() - this._getPositionRight();
487-
}
488-
489467
/**
490-
* This is using [ngStyle] rather than separate [style...] properties because [style.transform]
491-
* doesn't seem to work right now.
468+
* Recalculates and updates the inline styles. Note that this
469+
* should be used sparingly, because it causes a reflow.
492470
*/
493-
_getStyles() {
494-
return {
495-
marginLeft: `${this._getMarginLeft()}px`,
496-
marginRight: `${this._getMarginRight()}px`,
497-
transform: `translate3d(${this._getPositionOffset()}px, 0, 0)`
471+
private _updateStyles() {
472+
const marginLeft = this._left ? this._getSidenavEffectiveWidth(this._left, 'side') : 0;
473+
const marginRight = this._right ? this._getSidenavEffectiveWidth(this._right, 'side') : 0;
474+
const leftWidth = this._left ? this._getSidenavEffectiveWidth(this._left, 'push') : 0;
475+
const rightWidth = this._right ? this._getSidenavEffectiveWidth(this._right, 'push') : 0;
476+
477+
this._styles = {
478+
marginLeft: `${marginLeft}px`,
479+
marginRight: `${marginRight}px`,
480+
transform: `translate3d(${leftWidth - rightWidth}px, 0, 0)`
498481
};
499482
}
500483
}

0 commit comments

Comments
 (0)