angular中,防止按鈕的兩次點擊

       在個人項目中,用戶點擊按鈕後,若是網頁響應慢一點,用戶常會再次點擊一下。結果就觸發了兩次 click 操做。 若是是查詢還好,但若是是post,put請求時,可能就是大問題了。javascript

方案一:

因爲我用的是ng-zorro, 方案一是在組件中增長一個 isLoading=false 的變量, 按鈕上指定它的  nzLoading="isLoading" 。 zorro 文檔截圖:  java

在click事件中:  post

doSomeClick(){
    this.isLoading=true;
    this.service.createxxxx().subscribe( ()=> this.isLoading=false );
}

問題:優化

一、頁面上若是有多個button話,且都綁定到一個isLoading變量, 則在點擊一個按鈕時,全部按鈕都禁用了。若是想每一個按鈕單獨控制,那就須要爲每一個按鈕分配一個變量,這樣會引入很是多的變量,也是麻煩事。this

方案二:

利用throttleTime 來防止用戶兩次點擊,且但願用法改動很是小,好比
原來代碼:  (click)="login()"
新代碼   :    (click.once)="login()"spa

因此咱們實現一個  click.once的指令便可:code

import { Directive, Input, OnDestroy, OnInit, HostListener, Output, EventEmitter, Renderer2, ElementRef } from '@angular/core';
import { throttleTime } from 'rxjs/operators';
import { Subject, Subscription } from 'rxjs';

@Directive({
  // tslint:disable-next-line:directive-selector
  selector: '[click.once]'
})
export class OnceClickDirectiveDirective implements OnInit, OnDestroy {
  // tslint:disable-next-line:no-output-rename
  @Output('click.once') clickCall: EventEmitter<MouseEvent> = new EventEmitter();
  @Input() duration = 2000; // 必須是數字,傳入時要用綁定語法
  private $sub = new Subject<any>();
  private subscription: Subscription;
  constructor(
    private renderer: Renderer2, // Angular 2.x導入Renderer
    private element: ElementRef
  ) { }
  ngOnInit() {
    // 如此綁定事件亦可
    // this.renderer.listen(
    //   this.element.nativeElement, 'click', event => {
    //     event.preventDefault();
    //     event.stopPropagation();
    //     this.$sub.next(event);
    //   }
    // );
    this.subscription = this.$sub.pipe(
      throttleTime(this.duration)
    ).subscribe(e => {
      this.clickCall.emit(e);
    });
  }
  @HostListener('click', ['$event'])
  clickEvent(event: MouseEvent) {
    event.preventDefault();   // 一般是不須要冒泡的
    event.stopPropagation();
    this.$sub.next(event);
  }
  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}

代碼裏的時間間隔設置2秒,  一般接口在這個時間內都能返回結果了。對象

優化:blog

一、這個實現沒有任何禁用狀態的效果, 用戶能夠連續點擊,不過只響應一次。
若是點擊後想產生遮罩層,能夠在根組件中添加一個變量控制這個層的顯示,而後引入一個全局的service來註冊一個Subject對象。當點擊時,就向subject對象emit() 一下,而後定時再清除遮罩層。
我懶得麻煩。就不添加了!接口

相關文章
相關標籤/搜索