代码之家  ›  专栏  ›  技术社区  ›  Kamil Kiełczewski

角击脱钩

  •  0
  • Kamil Kiełczewski  · 技术社区  · 7 年前

    <div class="btn-plus" (click)="add(1)"> - </div>
    <div class="txt"> {{ myValue }} </div>
    <div class="btn-minus" (click)="add(-1)"> + </div>
    

    在我的component.ts文件中,我有:

    add(num) {
        this.myValue +=num;
        this.update(); // async function which will send PUT request
    }
    

    这个 this.update() 函数puts myValue 在大型JSON对象的适当字段中,并将其发送到服务器。

    :当用户在短时间内点击按钮加减10倍时,请求将被发送10次。但我只想发送一次请求-上次单击后0.5秒。 怎么做 ?

    2 回复  |  直到 6 年前
        1
  •  4
  •   user4676340 user4676340    7 年前

    使用 takeUntil 操作员:

    export class AppComponent  {
      name = 'Angular';
    
      calls = new Subject();
    
      service = {
        getData: () => of({ id: 1 }).pipe(delay(500)),
      };
    
      click() {
        this.calls.next(true);
        this.service.getData().pipe(
          takeUntil(this.calls),
        ).subscribe(res => console.log(res));
      }
    }
    

    Stackblitz

        2
  •  2
  •   Kamil Kiełczewski    7 年前

    这是我在互联网上找到的部分答案,但我愿意接受更好的解决方案(或改进到下面的解决方案(指令)):

    我在网上找到的 appDebounceClick

    我移除 update add 在.ts文件中:

    add(num) {
        this.myValue +=num;
    }
    

    并按以下方式更改模板:

    <div 
        appDebounceClick 
        (debounceClick)="update()" 
        (click)="add(1)" 
        class="btn-plus"
        > - 
    </div>
    <div class="txt"> {{ myValue }} </div>
    <!-- similar for btn-minus -->
    

    指令 作者 Cory Rylan (我把代码放在这里,以防将来link停止工作):

    import { Directive, EventEmitter, HostListener, Input, OnDestroy, OnInit, Output } from '@angular/core';
    import { Subject } from 'rxjs/Subject';
    import { Subscription } from 'rxjs/Subscription';
    import { debounceTime } from 'rxjs/operators';
    
    @Directive({
      selector: '[appDebounceClick]'
    })
    export class DebounceClickDirective implements OnInit, OnDestroy {
      @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);
      }
    }
    
        3
  •  1
  •   Charly    6 年前

    export const debounced = (cb, time) => {
      const db = new Subject();
      const sub = db.pipe(debounceTime(time)).subscribe(cb);
      const func = v => db.next(v);
    
      func.unsubscribe = () => sub.unsubscribe();
    
      return func;
    };
    

    一个例子是:

    import { Component, OnInit } from '@angular/core';
    import { debounced } from 'src/helpers';
    
    @Component({
      selector: 'app-example',
      // Click calls `debouncedClick` instead of `myClick` directly
      template: '<button (click)="debouncedClick($event)">Click This</button>'
    })
    export class Example implements OnDestroy {
      debouncedClick; // Subject.next function
    
      constructor() {
        // Done in constructor or ngOnInit for `this` to resolve
        this.debouncedClick = debounced($event => this.myClick($event), 800);
      }
    
      // Called after debounced resolves (800ms from last call)
      myClick($event) {
        console.log($event);
      }
    
      ngOnDestroy() {
        // Stay clean!
        this.debouncedFunc.unsubscribe();
      }
    }
    

    也可以反转用法,在click上调用“myClick”,并使 debounced 回调执行所需的操作。经销商的选择。

    (keyup) 事件也一样。

    不确定是否真的需要取消订阅-实现起来比研究内存泄漏要快:)

    推荐文章