欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Angular中自定义Debounce Click指令防止重复点击

程序员文章站 2022-06-24 17:42:14
在这篇文章中,我们将介绍使用 angular directive api 来创建自定义 debounce click 指令。该指令将处理在指定时间内多次点击事件,这有助于防...

在这篇文章中,我们将介绍使用 angular directive api 来创建自定义 debounce click 指令。该指令将处理在指定时间内多次点击事件,这有助于防止重复的操作。

对于我们的示例,我们希望在产生点击事件时,实现去抖动处理。接下来我们将介绍 directive api,hostlistener api 和 rxjs 中 debouncetime 操作符的相关知识。首先,我们需要创建 debounceclickdirective 指令并将其注册到我们的 app.module.ts 文件中:

import { directive, oninit } from '@angular/core';

@directive({
 selector: '[appdebounceclick]'
})
export class debounceclickdirective implements oninit {
 constructor() { }
 ngoninit() { }
}


@ngmodule({
 imports: [browsermodule],
 declarations: [
  appcomponent,
  debounceclickdirective
 ],
 providers: [],
 bootstrap: [appcomponent]
})
export class appmodule { }

angular 指令是没有模板的组件,我们将使用以下方式应用上面的自定义指令:

<button appdebounceclick>debounced click</button>

在上面 html 代码中的宿主元素是按钮,接下来我们要做的第一件事就是监听宿主元素的点击事件,因此我们可以将以下代码添加到我们的自定义指令中。

import { directive, hostlistener, oninit } from '@angular/core';

@directive({
 selector: '[appdebounceclick]'
})
export class debounceclickdirective implements oninit {
 constructor() { }

 ngoninit() { }

 @hostlistener('click', ['$event'])
 clickevent(event: mouseevent) {
  event.preventdefault();
  event.stoppropagation();
  console.log('click from host element!');
 }
}

在上面的例子中,我们使用了 angular @hostlistener 装饰器,该装饰器允许你轻松地监听宿主元素上的事件。在我们的示例中,第一个参数是事件名。第二个参数 $event,这用于告诉 angular 将点击事件传递给我们的 clickevent() 方法。

在事件处理函数中,我们可以调用 event.preventdefault()event.stoppropagation() 方法来阻止浏览器的默认行为和事件冒泡。

debounce events

现在我们可以拦截宿主元素的 click 事件,此时我们还需要有一种方法实现事件的去抖动处理,然后将它重新发送回父节点。这时我们需要借助事件发射器和 rxjs 中的 debounce 操作符。

import { directive, eventemitter, hostlistener, oninit, output } from '@angular/core';
import { subject } from 'rxjs/subject';
import 'rxjs/add/operator/debouncetime';

@directive({
  selector: '[appdebounceclick]'
})
export class debounceclickdirective implements oninit {
  @output() debounceclick = new eventemitter();
  private clicks = new subject<any>();

  constructor() { }

  ngoninit() {
    this.clicks
      .debouncetime(500)
      .subscribe(e => this.debounceclick.emit(e));
  }

  @hostlistener('click', ['$event'])
  clickevent(event: mouseevent) {
    event.preventdefault();
    event.stoppropagation();
    this.clicks.next(event);
  }
}

在上面的代码中,我们使用 angular @output 属性装饰器和 eventemitter 类,它们允许我们在指令上创建自定义事件。要发出事件,我们需要调用 eventemitter 实例上的 emit() 方法。

但我们不想立即发出点击事件,我们想做去抖动处理。为了实现这个功能,我们将使用 rxjs 中的 subject 类。在我们的代码中,我们创建一个主题来处理我们的点击事件。在我们的方法中,我们调用 next() 方法来让 subject 对象发出下一个值。此外我们也使用 rxjs 中 debouncetime 的操作符,这允许我们通过设置给定的毫秒数来去抖动点击事件。

一旦我们设置好了,我们现在可以在下面的模板中监听我们的自定义去抖动点击事件。

<button appdebounceclick (debounceclick)="log($event)">
 debounced click
</button>

现在,当我们点击我们的按钮时,它将延迟 500 毫秒。 500毫秒后,我们的自定义输出属性将会发出点击事件。现在我们有了基本的功能,我们需要做一些清理工作,并增加一些其它的功能。

unsubscribe

对于 rxjs 中 observables 和 subject 对象,一旦我们不再使用它们,我们必须取消订阅事件。如果我们没有执行取消订阅操作,有可能会出现内存泄漏。

import { directive, eventemitter, hostlistener, oninit, output, ondestroy } from '@angular/core';
import { subject } from 'rxjs/subject';
import { subscription } from "rxjs/subscription";
import 'rxjs/add/operator/debouncetime';

@directive({
  selector: '[appdebounceclick]'
})
export class debounceclickdirective implements oninit, ondestroy {
  @output() debounceclick = new eventemitter();
  private clicks = new subject<any>();
  private subscription: subscription;

  constructor() { }

  ngoninit() {
    this.subscription = this.clicks
      .debouncetime(500)
      .subscribe(e => this.debounceclick.emit(e));
  }

  ngondestroy() {
    this.subscription.unsubscribe();
  }

  @hostlistener('click', ['$event'])
  clickevent(event: mouseevent) {
    event.preventdefault();
    event.stoppropagation();
    this.clicks.next(event);
  }
}

要取消订阅,我们需要保存订阅时返回的订阅对象。当 angular 销毁组件时,它将调用 ondestroy 生命周期钩子,因此我们可以在这个钩子中,执行取消订阅操作。

custom inputs

我们指令的功能已基本齐全,它可以正常处理事件。接下来,我们将添加一些更多的逻辑,以便我们可以自定义去抖动时间。为此,我们将使用 @input 装饰器。

import { directive, eventemitter, hostlistener, oninit, output, ondestroy, input } from '@angular/core';
import { subject } from 'rxjs/subject';
import { subscription } from "rxjs/subscription";
import 'rxjs/add/operator/debouncetime';

@directive({
  selector: '[appdebounceclick]'
})
export class debounceclickdirective implements oninit, ondestroy {
  @input() debouncetime = 500;
  @output() debounceclick = new eventemitter();
  private clicks = new subject<any>();
  private subscription: subscription;

  constructor() { }

  ngoninit() {
    this.subscription = this.clicks
      .debouncetime(this.debouncetime)
      .subscribe(e => this.debounceclick.emit(e));
  }

  ngondestroy() {
    this.subscription.unsubscribe();
  }

  @hostlistener('click', ['$event'])
  clickevent(event: mouseevent) {
    event.preventdefault();
    event.stoppropagation();
    this.clicks.next(event);
  }
}

@input 装饰器允许我们将自定义延迟时间传递到我们的组件或指令中。在上面的代码中,我们可以通过组件的输入属性,来指定我们希望去抖动的时间。默认情况下,我们将其设置为 500 毫秒。

<button appdebounceclick (debounceclick)="log($event)" [debouncetime]="300">
 debounced click
</button>

参考资源

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。