Skip to content

Commit

Permalink
perf: improve scroll performance (#363)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: scroll events no longer trigger change detection
  • Loading branch information
arturovt authored Jan 30, 2021
1 parent 5c3e645 commit 8b63211
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 4 deletions.
2 changes: 1 addition & 1 deletion src/lib/picker/picker.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
[icons]="searchIcons"
[emojisToShowFilter]="emojisToShowFilter"
></emoji-search>
<section #scrollRef class="emoji-mart-scroll" (scroll)="handleScroll()" [attr.aria-label]="i18n.emojilist">
<section #scrollRef class="emoji-mart-scroll" [attr.aria-label]="i18n.emojilist">
<emoji-category
*ngFor="let category of activeCategories; let idx = index; trackBy: categoryTrack"
#categoryRef
Expand Down
30 changes: 27 additions & 3 deletions src/lib/picker/picker.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ import {
ElementRef,
EventEmitter,
Input,
NgZone,
OnDestroy,
OnInit,
Output,
QueryList,
Renderer2,
ViewChild,
ViewChildren,
} from '@angular/core';
Expand Down Expand Up @@ -62,7 +65,7 @@ const I18N: any = {
changeDetection: ChangeDetectionStrategy.OnPush,
preserveWhitespaces: false,
})
export class PickerComponent implements OnInit {
export class PickerComponent implements OnInit, OnDestroy {
@Input() perLine = 9;
@Input() totalFrequentLines = 4;
@Input() i18n: any = {};
Expand Down Expand Up @@ -134,6 +137,7 @@ export class PickerComponent implements OnInit {
name: 'Custom',
emojis: [],
};
private scrollListener!: () => void;

@Input()
backgroundImageFn: Emoji['backgroundImageFn'] = (
Expand All @@ -143,6 +147,8 @@ export class PickerComponent implements OnInit {
`https://unpkg.com/emoji-datasource-${this.set}@6.0.0/img/${this.set}/sheets-256/${this.sheetSize}.png`

constructor(
private ngZone: NgZone,
private renderer: Renderer2,
private ref: ChangeDetectorRef,
private frequently: EmojiFrequentlyService,
) {}
Expand Down Expand Up @@ -260,7 +266,22 @@ export class PickerComponent implements OnInit {
this.ref.markForCheck();
setTimeout(() => this.updateCategoriesSize());
});

this.ngZone.runOutsideAngular(() => {
// DOM events that are listened by Angular inside the template trigger change detection
// and also wrapped into additional functions that call `markForCheck()`. We listen `scroll`
// in the context of the root zone since it will not trigger change detection each time
// the `scroll` event is dispatched.
this.scrollListener = this.renderer.listen(this.scrollRef.nativeElement, 'scroll', () => {
this.handleScroll();
});
});
}

ngOnDestroy(): void {
this.scrollListener();
}

setActiveCategories(categoriesToMakeActive: Array<EmojiCategory>) {
if (this.showSingleCategory) {
this.activeCategories = categoriesToMakeActive.filter(
Expand Down Expand Up @@ -312,6 +333,7 @@ export class PickerComponent implements OnInit {
if (this.nextScroll) {
this.selected = this.nextScroll;
this.nextScroll = undefined;
this.ref.detectChanges();
return;
}
if (!this.scrollRef) {
Expand All @@ -321,7 +343,7 @@ export class PickerComponent implements OnInit {
return;
}

let activeCategory = null;
let activeCategory: EmojiCategory | undefined;
if (this.SEARCH_CATEGORY.emojis) {
activeCategory = this.SEARCH_CATEGORY;
} else {
Expand All @@ -346,8 +368,10 @@ export class PickerComponent implements OnInit {

this.scrollTop = target.scrollTop;
}
if (activeCategory) {
// This will allow us to run the change detection only when the category changes.
if (activeCategory && activeCategory.name !== this.selected) {
this.selected = activeCategory.name;
this.ref.detectChanges();
}
}
handleSearch($emojis: any[] | null) {
Expand Down

0 comments on commit 8b63211

Please sign in to comment.