纯前端短信倒计时需在请求成功(2xx)后启动setInterval,同步禁用按钮、设opacity、更新文案;倒计时结束或异常时清除定时器并恢复状态;秒数应从后端响应动态获取,兼顾移动端兼容性与异常处理。
纯前端实现短信倒计时,核心是用 setInterval 控制按钮状态和文案更新,同时必须在发送请求成功后再启动倒计时——否则用户点太快或网络失败会导致倒计时错乱或重复触发。
关键逻辑:按钮初始可点击 → 点击后立即禁用 + 改文案为“60s” → 启动定时器每秒减 1 → 归零后恢复可点击状态。
fetch 或 XMLHttpRequest 的 .then()(且仅当 HTTP 状态码为 2xx)里调用倒计时函数,避免请求未发出去就倒计时clearInterval),防止多次点击累积多个定时器disabled 属性禁用按钮,比单纯改 pointer-events: none 更可靠,能阻止表单提交和键盘交互disabled 和 style.opacity 要一起设只加 disabled 按钮会变灰但样式可能不统一(尤其自定义按钮),用户容易误以为没响应。必须同步调整视觉反馈。
示例代码片段:
立即学习“前端免费学习笔记(深入)”;
<button id="sendSmsBtn">发送验证码</button><script>const btn = document.getElementById('sendSmsBtn');let timer = null;function startCountdown(seconds = 60) { btn.disabled = true; btn.style.opacity = '0.6'; btn.textContent = `${seconds}s`; timer = setInterval(() => { seconds--; if (seconds <= 0) { clearInterval(timer); btn.disabled = false; btn.style.opacity = '1'; btn.textContent = '发送验证码'; return; } btn.textContent = `${seconds}s`; }, 1000);}btn.addEventListener('click', () => { // 这里应先发请求,成功后再调 startCountdown(60) fetch('/api/send-sms', { method: 'POST' }) .then(res => { if (res.ok) startCountdown(60); else throw new Error('发送失败'); }) .catch(err => console.error(err));});</script>
国内主流短信平台(如阿里云、腾讯云、极光)要求两次发送间隔不少于 60 秒,这是硬性限制,不是前端随便写的数字。但实际业务中可能需要动态读取后端返回的倒计时秒数(比如风控策略临时延长到 120 秒)。
startCountdown(60),应从接口响应体里取字段,例如 res.json().then(data => startCountdown(data.countdown))
setInterval 有节流(可能 10s 才触发一次),建议用 performance.now() + 递归 setTimeout 做更准的倒计时用户手快连点、请求超时、400/429 响应,都会导致按钮卡在“60s”不动。此时必须主动恢复按钮可用状态,并给出明确提示。
fetch().catch() 和 fetch().then(res => !res.ok) 里调用 clearInterval(timer) 并重置按钮startCountdown(),可在函数开头加 guard:if (timer) return;
429 Too Many Requests 时,应解析响应头 Retry-After 字段作为下次倒计时起点,而不是固定 60 秒