Angular 2 directive處理多次點選提交問題
阿新 • • 發佈:2019-01-10
在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就可以了