基于JS实现发送验证码的计时器效果
一、实现效果
需求:
- 点击按钮后开始读秒
- 读秒期间不可点击
- 读秒结束后可以继续点击
二、实现思路(步骤)
1.要做到计时器的效果,首先得实现一个读秒的效果
let count = 60; // 这里只做演示说明 Gif 中是 10 setInterval(() => { count = count - 1 }, 1000)
2.清除定时器的效果,处理状态
let count = 10; let timer = setInterval(() => { count = count - 1 }, 1000) // 这里我用 setTimeout 来做 clearInterval 的操作 setTimeout(function () { timer && clearInterval(timer) // 清理定时器的时机为 10 次之后 }, 10 * 1000)
注:
这里对于 setTimeout
清理 setInterval
这个定时器做一个说明
原本我的实现是在 setInterval
的执行中通过判断计数来销毁这个定时器的,但是发现定时器依然在执行,执行的原因是:setInterval
函数会在执行完回调函数后,创建一个新的定时器,并将旧的定时器销毁。 因此,当你在 setInterval
中执行 clearInterval
时,实际上是清除了一个已经被销毁的定时器。
通过以上两步,就可以实现了需求 1。将上述操作封装函数就可以得到一个简单的定时器功能了。
3.处理定时器的读秒期间不可点击实现(需求 2)
/** * @param {number} initCount 调用次数 * @param {(count: number) => count} time 定时器执行时间间隔 * @returns [开始调用, 计数器, 是否执行中] */ let tiggering = false; export const tigger = (initCount = 60, callback: (count: number) => count) => { let count = initCount; let timer: NodeJS.Timeout | null = null // 如果未触发,则可以执行定时器 if (!tiggering) { tiggering = true timer = setInterval(() => { count = count - 1 // 定时器每次执行后更新回调,这样可以在页面使用该状态 callback(count) }, time) } setTimeout(function () { // 定时器结束时设置更新触发状态 tiggering = false timer && clearInterval(timer) }, count * time) }
在这里我是将逻辑部分抽离为工具函数的使用,在实际项目中有步骤 2,在合适的时机做相对应的逻辑处理,基本够用了。
这段代码的实现基本没什么大的问题了,tiggering 状态的维护是放在了工具函数之外,感觉不是很优雅。在函数内部的实现话就需要用到闭包维护内部函数的形式来保护这个变量了,这点大家可以看看表达下自己的想法~
三、封装一个适用的 React 自定义 hook
实现思路大致和 步骤 3 类似:
import { useState } from 'react' /** * @param initCount 调用次数 * @param time 定时器执行时间间隔,这里支持修改真实的时间间隔 * @returns [开始调用, 计数器, 是否执行中] */ export default (initCount = 120, time = 1000): [() => void, number, boolean] => { // 维护调用次数 const [count, setCount] = useState(initCount) // 维护触发状态,用于 UI 部分实现禁用 const [tiggering, setTiggering] = useState(false) let timer: NodeJS.Timeout | null = null const tigger = () => { // 注:在这里又进行了一次 setCount 赋值操作,是为了解决第一次验证码读秒结束后, // 第二次验证码执行(tigger 函数调用)时,自定义 hook 已经执行,count 的值为 0 的情况 setCount(initCount) if (!tiggering) { setTiggering(true) timer = setInterval(() => { setCount(count => count - 1) }, time) } setTimeout(function () { timer && clearInterval(timer) setTiggering(false) }, initCount * time) } return [tigger, count, tiggering] }
组件中使用
这里简写实现过程
// ... 引入略 const [tigger, count, tiggering] = useTimeCount(10) const sendCode = () => { // 发送验证吗 getMailCode({ receiver: code }).then(res => { if (res) { tigger() // 这里可以执行其他逻辑,如发送成功的提示 } }) } return ( <Button disabled={tiggering} className='send-btn' onClick={sendCode}> {tiggering ? `${count}s` : 'Send code'} </Button> )
小结
在实现这套流程的时候,一开始觉得是个简单的实现,在实现过程中还是踩了一些小坑的,比如上文中说到的 clearInterval
的销毁时机的问题;以及考虑了下普通函数封装(步骤 3)。
到此这篇关于基于JS实现发送验证码的计时器效果的文章就介绍到这了,更多相关JS计时器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
javascript 兼容FF的onmouseenter和onmouseleave的代码
经过测试发现,例子1 在 ff下抖动的厉害,ie下稍微有点。 具体原因 其实就是 mouseout 的冒泡机制 引起的。2008-07-07JavaScript 中 this 关键字的作用及改变其上下文的方法
这篇文章主要介绍了JavaScript 中 this 关键字的作用和如何改变其上下文,通过使用 call, apply, bind 方法,可以改变函数中的 this 指向,从而在不同的上下文中使用同一个函数,需要的朋友可以参考下2023-01-01
最新评论