关于前端:优雅解决按钮重复点击问题

一、对思否的一点吐槽

思否上的许多按钮都没有做反复点击检测的问题,往往导致点击没反馈,屡次点击后忽然发表多条雷同内容,比方和一位同学的私信:

又如一个问题下的评论:

这个问题怎么解决呢?
简略点,应用一个lock标记,在申请收回时上锁,上锁后就不能够再发申请,能够在申请完结后解锁:

let clickButton = (function () {
  let lock = false
  return function (postParams) {
    if (lock) return
    lock = true
    // 假如应用axios发送申请
    axios.post('urlxxx', postParams).then(
      // 表单提交胜利
    ).catch(error => {
      // 表单提交出错
      console.log(error)
    }).finally(() => {
      // 不论成功失败 都解锁
      lock = false
    })
  }
})()

button.addEventListener('click', clickButton)

当然对于button按钮,能够应用setAttribute(‘disabled’, xxx)和removeAttribute(‘disabled’)来代替lock标记。

这个计划问题在于,对于每一次按钮点击,咱们都要写个lock标记,相当于反复的逻辑会呈现在代码的各个中央——是不是能够封装一下呢?

二、封装按钮锁定、解锁逻辑

写一个装璜器将逻辑封装起来:

function ignoreMultiClick(func, manual = false) {
  let lock = false
  return function (...args) {
    if (lock) return
    lock = true
    let done = () => (lock = false)
    if (manual) return func.call(this, ...args, done)
    let promise = func.call(this, ...args)
    Promise.resolve(promise).finally(done)
    return promise
  }
}

将想监听点击回调函数func作为传递给ignoreMultiClick进行装璜,会返回一个新的函数,应用该函数作为点击的回调事件即可。
这里同样用了一个标记lock来上锁,有两种办法解锁:

  1. 手动解锁:能够给ignoreMultiClick传递一个参数manual,意思是被动调用解锁。若该参数为truthy,则点击事件触发时会给原始的点击回调func传递一个参数done,done是一个函数,调用它能够解锁。
  2. 主动解锁:能够使原监听函数func返回一个promise,在该promise决定后主动执行解锁操作。因为Promise治理回调函数十分不便,并且像axios这样十分罕用的申请库返回值自身也是一个promise,所以默认状况应用这种形式。当然返回promise并不是必须的,有时候咱们在发申请前会进行一些验证,验证没通过则间接return,此时装璜器函数也能失常解决,因为应用Promise.resolve包裹了一下promise: Promise.resolve(promise).finally(done)

三、应用实例

主动解锁应用例子:

let clickButton = ignoreMultiClick(function (postParams) {
  if (!checkForm()) return // 假如有一些检测表单的操作,查看不通过则间接返回
  // 返回promise
  return axios.post('urlxxx', postParams).then(
    // 表单提交胜利
  ).catch(error => {
    // 表单提交出错
    console.log(error)
  })
})
button.addEventListener('click', clickButton)

手动解锁:

let clickButton = ignoreMultiClick(function (postParams, done) {
  if (!checkForm()) return done() // 表单验证不通过解锁
  axios.post('urlxxx', postParams).then(
    // 表单提交胜利
  ).catch(error => {
    // 表单提交出错
    console.log(error)
  }).finally(() => done()) // 申请完结解锁
})
button.addEventListener('click', clickButton)

一般场景下还是主动解锁比较简单,因为可能有多个条件分支,手动解锁须要在每一个返回的中央都调用done。

【腾讯云】轻量 2核2G4M,首年65元

阿里云限时活动-云数据库 RDS MySQL  1核2G配置 1.88/月 速抢

本文由乐趣区整理发布,转载请注明出处,谢谢。

您可能还喜欢...

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据