Skip to content

Commit dab742f

Browse files
crisbetokara
authored andcommitted
perf(tabs): reduce amount of reflows when aligning the ink bar (#2372)
1 parent e2989b3 commit dab742f

File tree

2 files changed

+36
-19
lines changed

2 files changed

+36
-19
lines changed

src/lib/tabs/tab-header.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
<div class="md-tab-label-container" #tabListContainer
1010
(keydown)="_handleKeydown($event)">
11-
<div class="md-tab-list" #tabList role="tablist" (cdkObserveContent)="_updatePagination()">
11+
<div class="md-tab-list" #tabList role="tablist" (cdkObserveContent)="_onContentChanges()">
1212
<ng-content></ng-content>
1313
<md-ink-bar></md-ink-bar>
1414
</div>

src/lib/tabs/tab-header.ts

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,13 @@ import {
55
NgZone,
66
QueryList,
77
ElementRef,
8-
ViewEncapsulation, ContentChildren, Output, EventEmitter, Optional
8+
ViewEncapsulation,
9+
ContentChildren,
10+
Output,
11+
EventEmitter,
12+
Optional,
13+
AfterContentChecked,
14+
AfterContentInit,
915
} from '@angular/core';
1016
import {RIGHT_ARROW, LEFT_ARROW, ENTER, Dir, LayoutDirection} from '../core';
1117
import {MdTabLabelWrapper} from './tab-label-wrapper';
@@ -44,7 +50,7 @@ const EXAGGERATED_OVERSCROLL = 60;
4450
'[class.md-tab-header-rtl]': "_getLayoutDirection() == 'rtl'",
4551
}
4652
})
47-
export class MdTabHeader {
53+
export class MdTabHeader implements AfterContentChecked, AfterContentInit {
4854
@ContentChildren(MdTabLabelWrapper) _labelWrappers: QueryList<MdTabLabelWrapper>;
4955

5056
@ViewChild(MdInkBar) _inkBar: MdInkBar;
@@ -106,12 +112,12 @@ export class MdTabHeader {
106112
this._tabLabelCount = this._labelWrappers.length;
107113
}
108114

109-
110115
// If the selected index has changed, scroll to the label and check if the scrolling controls
111116
// should be disabled.
112117
if (this._selectedIndexChanged) {
113118
this._scrollToLabel(this._selectedIndex);
114119
this._checkScrollingControls();
120+
this._alignInkBarToSelectedTab();
115121
this._selectedIndexChanged = false;
116122
}
117123

@@ -123,18 +129,6 @@ export class MdTabHeader {
123129
}
124130
}
125131

126-
/**
127-
* Waits one frame for the view to update, then updates the ink bar and scroll.
128-
* Note: This must be run outside of the zone or it will create an infinite change detection loop.
129-
*/
130-
ngAfterViewChecked(): void {
131-
this._zone.runOutsideAngular(() => {
132-
window.requestAnimationFrame(() => {
133-
this._alignInkBarToSelectedTab();
134-
});
135-
});
136-
}
137-
138132
_handleKeydown(event: KeyboardEvent) {
139133
switch (event.keyCode) {
140134
case RIGHT_ARROW:
@@ -149,6 +143,21 @@ export class MdTabHeader {
149143
}
150144
}
151145

146+
/**
147+
* Aligns the ink bar to the selected tab on load.
148+
*/
149+
ngAfterContentInit() {
150+
this._alignInkBarToSelectedTab();
151+
}
152+
153+
/**
154+
* Callback for when the MutationObserver detects that the content has changed.
155+
*/
156+
_onContentChanges() {
157+
this._updatePagination();
158+
this._alignInkBarToSelectedTab();
159+
}
160+
152161
/**
153162
* Updating the view whether pagination should be enabled or not
154163
*/
@@ -178,7 +187,7 @@ export class MdTabHeader {
178187
_isValidIndex(index: number): boolean {
179188
if (!this._labelWrappers) { return true; }
180189

181-
const tab = this._labelWrappers.toArray()[index];
190+
const tab = this._labelWrappers ? this._labelWrappers.toArray()[index] : null;
182191
return tab && !tab.disabled;
183192
}
184193

@@ -282,7 +291,10 @@ export class MdTabHeader {
282291
* should be called sparingly.
283292
*/
284293
_scrollToLabel(labelIndex: number) {
285-
const selectedLabel = this._labelWrappers.toArray()[labelIndex];
294+
const selectedLabel = this._labelWrappers
295+
? this._labelWrappers.toArray()[labelIndex]
296+
: null;
297+
286298
if (!selectedLabel) { return; }
287299

288300
// The view length is the visible width of the tab labels.
@@ -359,6 +371,11 @@ export class MdTabHeader {
359371
const selectedLabelWrapper = this._labelWrappers && this._labelWrappers.length
360372
? this._labelWrappers.toArray()[this.selectedIndex].elementRef.nativeElement
361373
: null;
362-
this._inkBar.alignToElement(selectedLabelWrapper);
374+
375+
this._zone.runOutsideAngular(() => {
376+
requestAnimationFrame(() => {
377+
this._inkBar.alignToElement(selectedLabelWrapper);
378+
});
379+
});
363380
}
364381
}

0 commit comments

Comments
 (0)