Vue全局指令防止重复点击(等待请求)

《vue之全局请求loading》之后,总觉得全局loading有时候不太…友好,所以总想将loading加到被点击的元素上面,于是乎就想到了点击事件与请求方法相关联,本想重写组件的click方法,但是这样对组件的影响太大,所以放弃了,最终想到了Vue全局指令。

一、实现原理

通过全局指令代替组件事件,在全局指令中绑定click事件,当dom被点击时,给dom添加禁用状态,利用闭包等方式获取到绑定的方法,通过await等待方法执行完毕然后去掉禁用;

二、使用

@click替换为v-con-click

<el-button type="primary" icon="el-icon-search" size="mini" v-con-click="handleQuery">搜索</el-button>

三、注意事项

1. 同步和异步回调只能选一种

同步通过await来等待去除禁用,而异步回调则是由自己判断去掉禁用。

同步(没有传参):

handleQuery(e) {
  console.log(e); // 没有传参时,默认为点击事件
  this.queryParams.pageNum = 1;
  await this.getList();
}

异步回调(没有传参):

handleQuery() {
  console.log(e); // 没有传参,默认为点击事件
  return (removeDisabled) => {
    this.queryParams.pageNum = 1;
    this.getList().then(res => {
      // 去掉组件禁用
      removeDisabled();
    })
  }
}

2. 异步回调需闭包

因需要回传回调方法,所以需添加一层闭包;

3. 有传参的方法需闭包

因有参数的方法相当于绑定时会自动执行一遍,所以添加闭包,来获取执行代码。

handleQuery(d) {
  return (removeDisabled) => {
    this.queryParams.pageNum = 1;
    this.getList().then(res => {
      // 去掉组件禁用
      removeDisabled();
    })
  }
}

所以对于有参数的方法异步回调就相当于两次闭包

handleQuery(d) {
  return (e) => {
  	console.log(e); // 点击事件
    return (removeDisabled) => {
      // 去掉组件禁用
      removeDisabled();
    }
  }
}

3. 其他问题

因想法特殊,可能会出现未知问题,目前暂未发现其他问题,如有问题,欢迎即使提出。

四、代码

const conClickDirective = {
  bind(el, binding, vnode) {
    el.addEventListener('click', async e => {
      let hasCb = false;
      el.classList.add('is-disabled');
      el.disabled = true;
      // 这里写点击事件的逻辑
      if (binding.value instanceof Function) {
        const res = await binding.value(e);
        if (res instanceof Function) {
          const d = res(() => {
            el.disabled = false;
            el.classList.remove('is-disabled');
          })
          if (!(d instanceof Promise)) {
            hasCb = true;
          } else {
            await d;
          }
        }
      }
      if (!hasCb) {
        el.disabled = false;
        el.classList.remove('is-disabled');
      }
    });
  }
};

// 全局注册自定义指令
Vue.directive('con-click', conClickDirective);

五、进阶版

进阶版:《Vue全局事件防止重复点击(等待请求)【进阶版】》

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
抱歉,作为语言AI模型,我没有具体的实现能力,无法为您提供需要的答案。但是,我可以为您提供一些有关Vue自定义指令的基本知识。 Vue中自定义指令可以全局注册或者局部注册。全局注册指令可以在任何Vue实例中使用,而局部注册指令只能在特定的Vue实例中使用。 全局注册自定义指令的方法是: ``` Vue.directive('directiveName', { //指令的定义 }) ``` 其中,'directiveName' 是指令的名称,{}内是指令的定义。 局部注册自定义指令的方法是: ``` new Vue({ directives: { directiveName: { // 指令的定义 } } }) ``` 在实现一个网站的登陆页面时,我们可以用自定义全局指令和局部指令来实现一些交互效果,例如: 全局指令: 1. 自动聚焦:当页面加载完成后,输入框自动聚焦。 ``` Vue.directive('focus', { inserted: function (el) { el.focus() } }) ``` 在输入框中加入 v-focus 即可实现自动聚焦效果。 2. 防抖动:在输入框中输入时,延迟一定时间后再发生请求防止因为输入过于频繁而发生多次请求。 ``` Vue.directive('debounce', { inserted: function (el, binding) { let timer el.addEventListener('input', () => { if (timer) { clearTimeout(timer) } timer = setTimeout(() => { binding.value() }, 500) }) } }) ``` 在输入框中加入 v-debounce="sendRequest",sendRequest为方法的名称即可实现防抖动效果。 局部指令: 1. 自动聚焦:同全局指令中的自动聚焦。 ``` directives: { focus: { inserted: function (el) { el.focus() } } } ``` 加入 v-focus 即可实现自动聚焦效果。 2. 双向绑定密码框的内容:使输入的密码随着输入动态显示到页面上。 ``` directives: { password: { twoWay: true, priority: 1000, bind: function () { this.handler = () => { this.set(this.el.value) } this.el.addEventListener('input', this.handler) }, update: function (newValue) { this.el.value = newValue }, unbind: function () { this.el.removeEventListener('input', this.handler) } } } ``` 在密码框中加入 v-model="password | password" 即可实现双向绑定效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

会功夫的李白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值