perf(tabs): reduce amount of reflows when aligning the ink bar (#2372)

This commit is contained in:
Kristiyan Kostadinov
2017-01-03 23:15:17 +01:00
committed by Kara
parent e2989b3b98
commit dab742fe44
2 changed files with 36 additions and 19 deletions
+1 -1
View File
@@ -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>
+35 -18
View File
@@ -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';
@@ -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;
@@ -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;
}
@@ -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:
@@ -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
*/
@@ -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;
}
@@ -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.
@@ -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);
});
});
}
}