Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf(module:rate): do not run change detection on focus and blur events if there are no output listeners #7182

Merged
merged 1 commit into from Jan 13, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
58 changes: 32 additions & 26 deletions components/rate/rate.component.ts
Expand Up @@ -13,8 +13,8 @@ import {
EventEmitter,
forwardRef,
Input,
NgZone,
OnChanges,
OnDestroy,
OnInit,
Optional,
Output,
Expand All @@ -25,10 +25,11 @@ import {
ViewEncapsulation
} from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Subject } from 'rxjs';
import { fromEvent } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

import { NzConfigKey, NzConfigService, WithConfig } from 'ng-zorro-antd/core/config';
import { NzDestroyService } from 'ng-zorro-antd/core/services';
import { BooleanInput, NgClassType, NumberInput } from 'ng-zorro-antd/core/types';
import { InputBoolean, InputNumber } from 'ng-zorro-antd/core/util';

Expand All @@ -47,8 +48,6 @@ const NZ_CONFIG_MODULE_NAME: NzConfigKey = 'rate';
[class.ant-rate-disabled]="nzDisabled"
[class.ant-rate-rtl]="dir === 'rtl'"
[ngClass]="classMap"
(blur)="onBlur($event)"
(focus)="onFocus($event)"
(keydown)="onKeyDown($event); $event.preventDefault()"
(mouseleave)="onRateLeave(); $event.stopPropagation()"
[tabindex]="nzDisabled ? -1 : 1"
Expand All @@ -72,14 +71,15 @@ const NZ_CONFIG_MODULE_NAME: NzConfigKey = 'rate';
</ul>
`,
providers: [
NzDestroyService,
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => NzRateComponent),
multi: true
}
]
})
export class NzRateComponent implements OnInit, OnDestroy, ControlValueAccessor, OnChanges {
export class NzRateComponent implements OnInit, ControlValueAccessor, OnChanges {
readonly _nzModuleName: NzConfigKey = NZ_CONFIG_MODULE_NAME;

static ngAcceptInputType_nzAllowClear: BooleanInput;
Expand All @@ -88,7 +88,7 @@ export class NzRateComponent implements OnInit, OnDestroy, ControlValueAccessor,
static ngAcceptInputType_nzAutoFocus: BooleanInput;
static ngAcceptInputType_nzCount: NumberInput;

@ViewChild('ulElement', { static: false }) private ulElement?: ElementRef;
@ViewChild('ulElement', { static: true }) ulElement!: ElementRef<HTMLUListElement>;

@Input() @WithConfig() @InputBoolean() nzAllowClear: boolean = true;
@Input() @WithConfig() @InputBoolean() nzAllowHalf: boolean = false;
Expand All @@ -107,7 +107,6 @@ export class NzRateComponent implements OnInit, OnDestroy, ControlValueAccessor,
starStyleArray: NgClassType[] = [];
dir: Direction = 'ltr';

private readonly destroy$ = new Subject<void>();
private hasHalf = false;
private hoverValue = 0;
private isFocused = false;
Expand All @@ -129,16 +128,18 @@ export class NzRateComponent implements OnInit, OnDestroy, ControlValueAccessor,

constructor(
public nzConfigService: NzConfigService,
private ngZone: NgZone,
private renderer: Renderer2,
private cdr: ChangeDetectorRef,
@Optional() private directionality: Directionality
@Optional() private directionality: Directionality,
private destroy$: NzDestroyService
) {}

ngOnChanges(changes: SimpleChanges): void {
const { nzAutoFocus, nzCount, nzValue } = changes;

if (nzAutoFocus && !nzAutoFocus.isFirstChange()) {
const el = this.ulElement!.nativeElement;
const el = this.ulElement.nativeElement;
if (this.nzAutoFocus && !this.nzDisabled) {
this.renderer.setAttribute(el, 'autofocus', 'autofocus');
} else {
Expand All @@ -161,17 +162,32 @@ export class NzRateComponent implements OnInit, OnDestroy, ControlValueAccessor,
.pipe(takeUntil(this.destroy$))
.subscribe(() => this.cdr.markForCheck());

this.directionality.change?.pipe(takeUntil(this.destroy$)).subscribe((direction: Direction) => {
this.directionality.change.pipe(takeUntil(this.destroy$)).subscribe((direction: Direction) => {
this.dir = direction;
this.cdr.detectChanges();
});

this.dir = this.directionality.value;
}

ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
this.ngZone.runOutsideAngular(() => {
fromEvent<FocusEvent>(this.ulElement.nativeElement, 'focus')
.pipe(takeUntil(this.destroy$))
.subscribe(event => {
this.isFocused = true;
if (this.nzOnFocus.observers.length) {
this.ngZone.run(() => this.nzOnFocus.emit(event));
}
});

fromEvent<FocusEvent>(this.ulElement.nativeElement, 'blur')
.pipe(takeUntil(this.destroy$))
.subscribe(event => {
this.isFocused = false;
if (this.nzOnBlur.observers.length) {
this.ngZone.run(() => this.nzOnBlur.emit(event));
}
});
});
}

onItemClick(index: number, isHalf: boolean): void {
Expand Down Expand Up @@ -215,22 +231,12 @@ export class NzRateComponent implements OnInit, OnDestroy, ControlValueAccessor,
this.updateStarStyle();
}

onFocus(e: FocusEvent): void {
this.isFocused = true;
this.nzOnFocus.emit(e);
}

onBlur(e: FocusEvent): void {
this.isFocused = false;
this.nzOnBlur.emit(e);
}

focus(): void {
this.ulElement!.nativeElement.focus();
this.ulElement.nativeElement.focus();
}

blur(): void {
this.ulElement!.nativeElement.blur();
this.ulElement.nativeElement.blur();
}

onKeyDown(e: KeyboardEvent): void {
Expand Down