Недавно я обнаружил, что производительность страницы сильно затруднялась директивой angular, которая несколько раз использовалась в его шаблоне. Причина более низкой производительности была обнаружена в следующем фрагменте кода:
@HostListener('window:keydown', ['$event'])
private keydown(e: KeyboardEvent) {
this.doSomething(e);
}
Я подозревал, что проблема может быть вызвана регистрацией нескольких прослушивателей событий в событии keydown окна, потому что новый был зарегистрирован каждый раз, когда эта директива повторялась на странице. Чтобы проверить эту теорию, я создал службу с RxJS Subject для обработки этого события клавиатуры:
@Injectable()
export class KeyboardService {
constructor() {
window.addEventListener('keydown', event => {
this.keydownSubject.next(event);
});
}
}
private keydownSubject: Subject<KeyboardEvent> = new Subject<KeyboardEvent>();
get keydown(): Observable<KeyboardEvent> {
return this.keydownSubject.asObservable();
}
Затем я удалил @HostListener
в директиве и подписался на этот объект службы в ngOnInit:
export class KeydownEventDirective implements OnInit, OnDestroy {
constructor(private keyboardService: KeyboardService) {}
private keydown(e: KeyboardEvent) {
this.doSomething(e);
}
private keydownSubscription: Subscription;
ngOnInit() {
this.keydownSubscription =
this.keyboardService.keydown.subscribe(e => {
this.keydown(e);
});
}
ngOnDestroy() {
this.keydownSubscription.unsubscribe();
}
...
}
Решение ускорило страницу, и мне было трудно понять, почему это так. Почему @HostListener
или добавление нескольких прослушивателей событий к событию keydown окна будет более пагубным для производительности страницы, чем несколько подписей на тему RxJS? Может ли быть, что angular HostListeners не являются пассивными слушателями по умолчанию?