我最近发现,在其模板上多次使用的角度指令极大地阻碍了页面的性能。在下面的代码中找到了性能降低的原因:
@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主题的多个订阅更不利于页面的性能?可能是默认情况下角度HostListeners不是被动侦听器吗?
答案 0 :(得分:1)
它与主题无关,首先,注入服务是单例,因此将为所有指令提供一个实例,第二个在单例服务中,您在构造函数中注册单个方法来处理调用的keydown事件如果您在控制台中打印一条消息,您将看到一个电话。
但是使用Hostlistener by指令会有一个由标签注册的事件和在keydown事件上多次执行。
答案 1 :(得分:0)
您可能尝试在多个组件上捕获相同的事件,这将导致您执行所有订阅方法(private keydown(e: KeyboardEvent)
),无论您是否按下了哪个键,因为您正在添加全局窗口级别的事件监听器。
与您在服务中所做的相比,它更好一些,尽管我很确定您也可以使用
public emitter: EventEmitter<any> = new EventEmitter<any>();
@HostListener('window:keydown', ['$event'])
private keydown(e: KeyboardEvent) {
this.doSomething(e);
}
private doSomething(event: any): void {
this.emitter.emit(event);
}
在您的服务中,然后公开EventEmitter
或Subject
您的组件可以订阅并抓住keyDown
事件。