我在Angular2中实现了一个简单的无限滚动指令。
我使用@HostListener('window:scroll')
来获取滚动事件并解析$target
中的数据。
问题是,对于每个滚动事件,都会再次检查所有内容而不需要。
我检查了离子infinite-scroll
指令的灵感,但他们没有使用@HostListener
,我猜他们需要更精细的控制。
我在搜索https://github.com/angular/angular/issues/13248时最终遇到了这个问题,但无法找到任何方法来做我想要的事情。
我认为如果我创建一个Observable,使用debounce和push(next)项目订阅它,我会达到我想要的行为,但我无法做到。
答案 0 :(得分:38)
我会利用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) {
...
}
<强> Plunker Example 强>
答案 1 :(得分:4)
我真的很喜欢@yurzui的解决方案,并且我更新了很多代码来使用它。但是,我认为它包含一个错误。在原始代码中,每个类只有一个timeout
,但实际上每个 instance 都需要一个。
用Angular术语来说,这意味着如果在容器中实例化了使用@debounce()
的组件多次,则每个实例化将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__
属性的歧义可能会更加复杂。
答案 2 :(得分:1)
使用 fromEvent
和 throttleTime
运算符可以实现执行此操作的 RXJS 方式。
不是使用 @HostListener
装饰您的事件处理程序,而是使用 fromEvent
(例如,在 ngOnInit
方法中)从事件创建可观察对象,然后使用 { {1}}。
throttleTime
使用 RXJS 的一个优点是您可以将自定义调度程序传递给 ...
import {fromEvent, Subscription} from 'rxjs';
import {tap, throttleTime} from 'rxjs/operators';
export class MyComponent implements OnInit, OnDestroy {
private eventSub: Subscription;
ngOnInit() {
this.eventSub = fromEvent(window, 'scroll').pipe(
throttleTime(300), // emits once, then ignores subsequent emissions for 300ms, repeat...
tap(event => this.scroll(event))
).subscribe();
}
scroll(event) {
...
}
ngOnDestroy() {
this.eventSub.unsubscribe(); // don't forget to unsubscribe
}
}
运算符以实现不同的行为。例如,您可以按动画帧速率限制事件发射(例如,限制触摸事件的发射)。
throttleTime