js如何解决按钮”重复点击“的问题
一、如何解决按钮”重复点击“的问题呢?
简单点,使用一个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
来上锁,有两种方法解锁:
手动解锁:可以给ignoreMultiClick
传递一个参数manual
,意思是主动调用解锁。若该参数为truthy
,则点击事件触发时会给原始的点击回调func
传递一个参数done
,done
是一个函数,调用它可以解锁。
自动解锁:可以使原监听函数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。
码云笔记 » js如何解决按钮”重复点击“的问题