Skip to content

Commit

Permalink
perf(tabs): reduce amount of reflows when aligning the ink bar (#2372)
Browse files Browse the repository at this point in the history
  • Loading branch information
crisbeto authored and kara committed Jan 3, 2017
1 parent e2989b3 commit dab742f
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 19 deletions.
2 changes: 1 addition & 1 deletion src/lib/tabs/tab-header.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

<div class="md-tab-label-container" #tabListContainer
(keydown)="_handleKeydown($event)">
<div class="md-tab-list" #tabList role="tablist" (cdkObserveContent)="_updatePagination()">
<div class="md-tab-list" #tabList role="tablist" (cdkObserveContent)="_onContentChanges()">
<ng-content></ng-content>
<md-ink-bar></md-ink-bar>
</div>
Expand Down
53 changes: 35 additions & 18 deletions src/lib/tabs/tab-header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ import {
NgZone,
QueryList,
ElementRef,
ViewEncapsulation, ContentChildren, Output, EventEmitter, Optional
ViewEncapsulation,
ContentChildren,
Output,
EventEmitter,
Optional,
AfterContentChecked,
AfterContentInit,
} from '@angular/core';
import {RIGHT_ARROW, LEFT_ARROW, ENTER, Dir, LayoutDirection} from '../core';
import {MdTabLabelWrapper} from './tab-label-wrapper';
Expand Down Expand Up @@ -44,7 +50,7 @@ const EXAGGERATED_OVERSCROLL = 60;
'[class.md-tab-header-rtl]': "_getLayoutDirection() == 'rtl'",
}
})
export class MdTabHeader {
export class MdTabHeader implements AfterContentChecked, AfterContentInit {
@ContentChildren(MdTabLabelWrapper) _labelWrappers: QueryList<MdTabLabelWrapper>;

@ViewChild(MdInkBar) _inkBar: MdInkBar;
Expand Down Expand Up @@ -106,12 +112,12 @@ export class MdTabHeader {
this._tabLabelCount = this._labelWrappers.length;
}


// If the selected index has changed, scroll to the label and check if the scrolling controls
// should be disabled.
if (this._selectedIndexChanged) {
this._scrollToLabel(this._selectedIndex);
this._checkScrollingControls();
this._alignInkBarToSelectedTab();
this._selectedIndexChanged = false;
}

Expand All @@ -123,18 +129,6 @@ export class MdTabHeader {
}
}

/**
* Waits one frame for the view to update, then updates the ink bar and scroll.
* Note: This must be run outside of the zone or it will create an infinite change detection loop.
*/
ngAfterViewChecked(): void {
this._zone.runOutsideAngular(() => {
window.requestAnimationFrame(() => {
this._alignInkBarToSelectedTab();
});
});
}

_handleKeydown(event: KeyboardEvent) {
switch (event.keyCode) {
case RIGHT_ARROW:
Expand All @@ -149,6 +143,21 @@ export class MdTabHeader {
}
}

/**
* Aligns the ink bar to the selected tab on load.
*/
ngAfterContentInit() {
this._alignInkBarToSelectedTab();
}

/**
* Callback for when the MutationObserver detects that the content has changed.
*/
_onContentChanges() {
this._updatePagination();
this._alignInkBarToSelectedTab();
}

/**
* Updating the view whether pagination should be enabled or not
*/
Expand Down Expand Up @@ -178,7 +187,7 @@ export class MdTabHeader {
_isValidIndex(index: number): boolean {
if (!this._labelWrappers) { return true; }

const tab = this._labelWrappers.toArray()[index];
const tab = this._labelWrappers ? this._labelWrappers.toArray()[index] : null;
return tab && !tab.disabled;
}

Expand Down Expand Up @@ -282,7 +291,10 @@ export class MdTabHeader {
* should be called sparingly.
*/
_scrollToLabel(labelIndex: number) {
const selectedLabel = this._labelWrappers.toArray()[labelIndex];
const selectedLabel = this._labelWrappers
? this._labelWrappers.toArray()[labelIndex]
: null;

if (!selectedLabel) { return; }

// The view length is the visible width of the tab labels.
Expand Down Expand Up @@ -359,6 +371,11 @@ export class MdTabHeader {
const selectedLabelWrapper = this._labelWrappers && this._labelWrappers.length
? this._labelWrappers.toArray()[this.selectedIndex].elementRef.nativeElement
: null;
this._inkBar.alignToElement(selectedLabelWrapper);

this._zone.runOutsideAngular(() => {
requestAnimationFrame(() => {
this._inkBar.alignToElement(selectedLabelWrapper);
});
});
}
}

0 comments on commit dab742f

Please sign in to comment.