1. 程式人生 > >Angular 2 directive處理多次點選提交問題

Angular 2 directive處理多次點選提交問題

    在Angualr中,經常需要處理多次短時間重複點選提交等操作;比如,頁面的一些操作需要經常提交請求到後臺處理資料,或者搜尋功能對於每一個輸入的字元都到後端搜尋處理返回結果,對短時間內頻繁的重複提交來說,我們只需要這段時間內最後一次的提交請求;否則這些無效的網路請求會加大伺服器的負擔;在angular中,我們可以通過建立一個延時執行的click的directive來處理這種情況;

1>首先需要定義個directive,監聽當前元素的click事件;

import { Directive, HostListener, OnInit } from '@angular/core';

@Directive({
  selector: '[appDebounceClick]'
})
export class DebounceClickDirective implements OnInit {
  constructor() { }

  ngOnInit() { }

  @HostListener('click', ['$event'])
  clickEvent(event) {
    event.preventDefault();
    event.stopPropagation();
    console.log('Click from Host Element!');
  }
}

    HostListener這個裝飾器可以監聽directive作用的dom元素的click事件,第二個引數$event告訴Angular傳遞點選事件到directive中去; event.preventDefault();event.stopPropagation() 防止事件繼續向parent component中傳遞;

2>Debounce Events

我們需要攔截點選事件然後延遲這些點選事件的執行,直到一段時間內最後一次點選,最後把事件的處理操作交給parent來處理;

import { Directive, EventEmitter, HostListener, OnInit, Output } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { debounceTime } from 'rxjs/operators';

@Directive({
  selector: '[appDebounceClick]'
})
export class DebounceClickDirective implements OnInit {
  @Output() debounceClick = new EventEmitter();
  private clicks = new Subject();

  constructor() { }

  ngOnInit() {
    this.clicks.pipe(
      debounceTime(500)
    ).subscribe(e => this.debounceClick.emit(e));
  }

  @HostListener('click', ['$event'])
  clickEvent(event) {
    event.preventDefault();
    event.stopPropagation();
    this.clicks.next(event);
  }
}

這裡使用subject的.next來傳遞點選事件,然後使用rxjs的函式操作符debounceTime來處理延時事件,在指定事件內只處理最後一次操作,最後呼叫emit傳遞點選事件的操作到parent中去繼續處理;

3>最後需要注意的是,destory中取消訂閱,完整程式碼

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

@Directive({
    selector: '[appDebounceClick]'
})
export class DebounceClickDirective implements OnInit {
    @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);
    }
}

這裡將延遲時間作為引數傳遞進來;

頁面使用該directive的方法

<button appDebounceClick (debounceClick)="log()" [debounceTime]="700">Debounced Click</button>
這樣就可以需要重複大量提交的地方,加上該directive就可以了