Angular中自定义Debounce Click指令防止重复点击
在这篇文章中,我们将介绍使用 Angular Directive API 来创建自定义 debounceclick指令。该指令将处理在指定时间内多次点击事件,这有助于防止重复的操作。
对于我们的示例,我们希望在产生点击事件时,实现去抖动处理。接下来我们将介绍 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>
参考资源
creating-a-custom-debounce-click-directive-in-angular
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
您可能感兴趣的文章:
- angularjs-指令-防止重复提交,第一次点击提交后必须相隔几秒后才能点击
- 防止快速连续点击按钮重复提交数据之一(自定义方法实现)
- Rx_java(7)Rx_java2操作符(throttleFirst、debounce )介绍-防止按钮被重复点击案例
- 工具类——防止重复点击的 onClickListener
- asp.net中如何防止用户重复点击提交按钮
- 在 Angular2 中实现自定义校验指令(确认密码)的方法
- 防止按钮多次点击、重复提交【基于Jquery】
- (转)[Android] 防止连续点击打开两个重复页面的小技巧
- 防止重复多次点击按钮
- 使用自定义注解和token防止表单重复提交
- Android防止按钮重复点击示例代码
- Log4net使用总结,防止自定义的logger和root重复写入日志
- 项目总结之防止连续点击打开两个重复页面的技巧
- button防止被重复点击的相关方法(详细版)
- (四上)Angular指令,ng-bind指令,ng-init 指令,ng-click指令,ng-repeat 指令
- ajax防止多次点击重复提交
- 【Android】Android防止过快点击造成多次事件执行(防止按钮重复点击)
- Log4net使用总结,防止自定义的logger和root重复写入日志
- 安卓Toast自定义及防止重复显示
- android click防止多次重复点击