在 Angular 中自定义一个节流指令

2020-05-11  本文已影响0人  daozun

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

上一篇下一篇

猜你喜欢

热点阅读