我正在Angular2中实现一个简单的无限滚动指令.我正在使用@HostListener('window:scroll')
滚动事件并解析数据$target
.
问题是,对于每个滚动事件,一切都将被再次检查而不需要.
我检查了离子infinite-scroll
指令的灵感,但他们没有使用@HostListener
,我猜他们需要更精细的控制.
我在搜索https://github.com/angular/angular/issues/13248时最终遇到了这个问题,但找不到任何方法来做我想要的事情.
我想如果我创建一个Observable,用debounce和push(next)项目订阅它,我会达到我想要的行为,但我无法做到这一点.
yur*_*zui 43
我会利用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;
};
}
Run Code Online (Sandbox Code Playgroud)
并按如下方式使用:
@HostListener('window:scroll', ['$event'])
@debounce()
scroll(event) {
...
}
Run Code Online (Sandbox Code Playgroud)
小智 12
我真的很喜欢@yurzui的解决方案,我更新了很多代码来使用它。但是,我认为它包含一个错误。在原始代码中,timeout
每个类只有一个,但实际上每个实例都需要一个。
在 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;
};
}
Run Code Online (Sandbox Code Playgroud)
当然,可以更复杂地消除合成__timeout__
属性的歧义。
执行此操作的 RXJS 方法可以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
}
}
Run Code Online (Sandbox Code Playgroud)
使用 RXJS 的优点之一是您可以将自定义调度程序传递给throttleTime
操作员以实现不同的行为。例如,您可以通过动画帧速率来限制事件发射(例如,限制触摸事件的发射)。
import {animationFrameScheduler, ...} from 'rxjs';
...
this.eventSub = fromEvent(window, 'touchmove').pipe(
throttleTime(0, animationFrameScheduler),
tap(event => ...)
).subscribe();
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
7918 次 |
最近记录: |