1. 需求
最近在开发中,接到一个新需求,就是将 每次点击按钮都发送请求 修改成 如果在某个时间段重复点击那么就只触发一次,没错这就是经常说的 节流
2. directive
我们可以做一个 directive 进行逻辑抽离和代码复用
ng g directive throttle-click
生成一个 directive
import { Directive, OnInit } from '@angular/core';
@Directive({
selector: '[appThrottleClick]'
})
export class ThrottleClickDirective implements OnInit {
constructor() {}
ngOnInit() {}
}
我们首先需要完成对点击函数的监听,所以如下代码:
import { Directive, HostListener, OnInit } from '@angular/core';
@Directive({
selector: '[appThrottleClick]'
})
export class ThrottleClickDirective implements OnInit {
constructor() {}
ngOnInit() {}
@HostListener('click', ['$event'])
clickEvent(event) {
event.preventDefault();
event.stopPropagation();
console.log('Click from Host Element!');
}
}
<button appThrottleClick>Debounced Click</button>
我们可以把这个 directive 看作一个中转站,在模板中点击函数先在这里被截取,然后再在特定时间内返回到与模板相对应的 TS 文件。
3. 完整代码
import {
Directive,
EventEmitter,
HostListener,
Input,
OnDestroy,
OnInit,
Output
} from '@angular/core';
import { Subject, Subscription } from 'rxjs';
import { debounceTime } from 'rxjs/operators';
@Directive({
selector: '[appThrottleClick]'
})
export class ThrottleClickDirective implements OnInit, OnDestroy {
@Input() debounceTime = 500;
@Output() debounceClick = new EventEmitter();
private clicks = new Subject();
private subscription: Subscription;
constructor() {}
ngOnInit() {
this.subscription = this.clicks
.pipe(debounceTime(this.debounceTime))
.subscribe(e => this.debounceClick.emit(e));
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
@HostListener('click', ['$event'])
clickEvent(event) {
event.preventDefault();
event.stopPropagation();
this.clicks.next(event);
}
}
先初始化了一个 Subject 也就是 clicks, 然后在 next 中把监听到的函数流传递了下去,通过 pipe 运算符把延时函数 debounceTime 包裹在里面,最后在 subscribe 的时候通过 @Output 传递了回去。
文章参考自: Creating a Custom Debounce Click Directive in Angular
网友评论