Debounce событие @HostListener
Я реализую простую директиву бесконечной прокрутки в Angular2. Я использую @HostListener('window:scroll')
чтобы получить событие прокрутки и анализ данных из $target
.
Вопрос в том, что для каждого события прокрутки все будет проверено еще раз без необходимости.
Я проверил ионную директиву infinite-scroll
для вдохновения, но они не используют @HostListener
, им нужен более @HostListener
контроль, я думаю.
Я попал в эту проблему во время поиска https://github.com/angular/angular/issues/13248, но не смог найти способ сделать то, что я хочу.
Я думаю, что если я создам Observable, подпишусь на него с помощью debounce и добавлю (следующий) элементы к нему, я достигну желаемого поведения, но я не в состоянии это сделать.
Ответы
Ответ 1
Я бы использовал декоратор метода debounce, как:
export function debounce(delay: number = 300): MethodDecorator {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
let timeout = null
const original = descriptor.value;
descriptor.value = function (...args) {
clearTimeout(timeout);
timeout = setTimeout(() => original.apply(this, args), delay);
};
return descriptor;
};
}
и используйте его следующим образом:
@HostListener('window:scroll', ['$event'])
@debounce()
scroll(event) {
...
}
Пример плунжера
Ответ 2
Мне очень нравится решение @yurzui, и я обновил много кода, чтобы использовать его. Тем не менее, я думаю, что это содержит ошибку. В исходном коде есть только один timeout
на класс, но на практике он необходим для каждого экземпляра.
В угловых терминах это означает, что если компонент, в котором используется @debounce()
несколько раз в контейнере, то каждое создание будет cancelTimeout
время до предыдущего создания и будет cancelTimeout
только последнее.
Я предлагаю этот небольшой вариант, чтобы устранить эту проблему:
export function debounce(delay: number = 300): MethodDecorator {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const original = descriptor.value;
const key = '__timeout__${propertyKey}';
descriptor.value = function (...args) {
clearTimeout(this[key]);
this[key] = setTimeout(() => original.apply(this, args), delay);
};
return descriptor;
};
}
Конечно, можно быть более изощренным в устранении неоднозначности синтетического свойства __timeout__
.