我在Angular2中实现了一个简单的无限滚动指令。我使用@HostListener('window:scroll')获取scroll事件并解析来自$target的数据。
问题是,对于每个滚动事件,都会再次检查所有内容,而不需要检查。
我查看了ionic infinite-scroll指令以获取灵感,但他们不使用@HostListener,我猜他们需要更细粒度的控制。
我在搜索https://github.com/angular/angular/issues/13248时遇到了这个问题,但找不到任何方法来做我想做的事情。
我想如果我创建一个可观察对象,订阅它并将下一个项目推到它上面,我就会达到我想要的行为,但我无法做到这一点。
发布于 2017-06-20 00:34:26
我会利用去抖动方法装饰器,如下所示:
export function debounce(delay: number = 300): MethodDecorator {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const timeoutKey = Symbol();
const original = descriptor.value;
descriptor.value = function (...args) {
clearTimeout(this[timeoutKey]);
this[timeoutKey] = setTimeout(() => original.apply(this, args), delay);
};
return descriptor;
};
}并按如下方式使用它:
@HostListener('window:scroll', ['$event'])
@debounce()
scroll(event) {
...
}发布于 2019-03-01 04:34:58
我真的很喜欢@yurzui的解决方案,我更新了很多代码来使用它。但是,我认为它包含了一个错误。在原始代码中,每个类只有一个timeout,但实际上每个实例都需要一个。
从角度上讲,这意味着如果使用@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__属性的歧义。
发布于 2021-05-15 17:01:53
可以结合使用fromEvent和throttleTime运算符来实现这一点。
与使用@HostListener修饰事件处理程序不同,您可以使用fromEvent (例如,在ngOnInit方法中)从事件创建一个可观察对象,然后使用throttleTime限制事件的发出。
...
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
}
}使用RXJS的一个优点是,您可以将自定义调度器传递给throttleTime操作符,以实现不同的行为。例如,您可以通过动画帧速率来限制事件发射(例如,限制触摸事件的发射)。
import {animationFrameScheduler, ...} from 'rxjs';
...
this.eventSub = fromEvent(window, 'touchmove').pipe(
throttleTime(0, animationFrameScheduler),
tap(event => ...)
).subscribe();https://stackoverflow.com/questions/44634992
复制相似问题