angular中,防止按钮的两次点击 原

       在我的项目中,用户点击按钮后,如果网页响应慢一点,用户常会再次点击一下。结果就触发了两次 click 操作。 如果是查询还好,但如果是post,put请求时,可能就是大问题了。

方案一:

由于我用的是ng-zorro, 方案一是在组件中增加一个 isLoading=false 的变量, 按钮上指定它的  nzLoading="isLoading" 。 zorro 文档截图:  

在click事件中:  

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

问题:

1、页面上如果有多个button话,且都绑定到一个isLoading变量, 则在点击一个按钮时,所有按钮都禁用了。如果想每个按钮单独控制,那就需要为每个按钮分配一个变量,这样会引入非常多的变量,也是麻烦事。

方案二:

利用throttleTime 来防止用户两次点击,且希望用法改动非常小,比如 原来代码:  (click)="login()" 新代码   :    (click.once)="login()"

所以我们实现一个  click.once的指令即可:

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秒,  通常接口在这个时间内都能返回结果了。

优化:

1、这个实现没有任何禁用状态的效果, 用户可以连续点击,不过只响应一次。 如果点击后想产生遮罩层,可以在根组件中添加一个变量控制这个层的显示,然后引入一个全局的service来注册一个Subject对象。当点击时,就向subject对象emit() 一下,然后定时再清除遮罩层。 我懒得麻烦。就不添加了!

(adsbygoogle = window.adsbygoogle || []).push({});

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏祥子的故事

R读取spss的sav格式数据

相对而言,处理英文的就很容易,方法也很容易查找到。下面是我对这两种情况的一个总结。

16830
来自专栏米扑专栏

Python pyspider 安装与开发

PySpider是一个国人编写的强大的网络爬虫系统并带有强大的WebUI。采用Python语言编写,分布式架构,支持多种数据库后端,强大的WebUI支持脚本编辑...

19130
来自专栏米扑专栏

Clojure 学习入门(19)—— 数组

user=> (into-array [1 2 3]) #<Integer[] [Ljava.lang.Integer;@4b0ea9ba> user=> (s...

10040
来自专栏祥子的故事

第四章:对象

决定了该对象可以保存什么类型的值,可以进行什么样的操作,遵循什么样的规则。用内建函数type()查看。类型也是对象

13150
来自专栏祥子的故事

第六章:序列--字符串、列表和元组

14210
来自专栏祥子的故事

两数之和(二)

伪代码中使用了hash方法,由于不熟悉,故采用类似的方法来做。时间复杂度上可能不符合题意。

15140
来自专栏祥子的故事

第三章: Python基础

在Python中,对象是通过引用传递的。在赋值时,不管这对象是新创建的还是已经存在的,都是将该对象的引用(并不是值)赋值给变量。

16730
来自专栏祥子的故事

数组旋转

24040
来自专栏米扑专栏

Github Makedown 语法入门

GitHub上创建GitHub项目,会包含了一个 README.md 文件,此文件编辑就会用到Markdown

19140
来自专栏米扑专栏

Clojure 学习入门(17)—— 异常处理

异常处理 Clojure代码里面抛出来的异常都是运行时异常。当然从Clojure代码里面调用的java代码还是可能抛出那种需要检查的异常的。

7720

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励