从入门小白到精通,玩转 React Native 鸿蒙跨平台开发:通用验证码倒计时器(含重新发送逻辑)鸿蒙实战
定义countDown状态:存储倒计时剩余秒数,初始值为0(默认无倒计时);定义isDisabled状态:存储按钮是否禁用,初始值为false(默认可点击)。// 倒计时时长btnTextNormal: '获取验证码',btnTextCounting: (time) => `${time}秒 · 重新发送`,// 函数式更新,避免状态偏差}, 1000);} else {// 点击事件consol
一、验证码倒计时器 核心需求 & 核心特性
1. 核心技术点拆解(零基础易懂,无门槛)
实现本倒计时器仅需掌握 3 个 React Native 入门级核心知识点,吃透这 3 个知识点,不仅能实现倒计时,更能举一反三实现所有定时器相关功能:
- useState 状态管理:定义「倒计时剩余秒数、按钮是否禁用」两个核心状态,通过修改状态值实现按钮文字、禁用状态的动态更新;
- useEffect 副作用钩子:核心实现「定时器的创建、倒计时逻辑执行、定时器的清除销毁」,是整个倒计时器的核心逻辑载体;
- TouchableOpacity 按钮组件:鸿蒙端最常用的可点击组件,支持
disabled禁用属性,完美适配倒计时的禁用 / 启用状态切换。
二、核心原理:零基础拆解 验证码倒计时完整逻辑
很多新手觉得倒计时器有难度,本质是没理清「状态 + 定时器」的联动逻辑,其实整个倒计时的核心逻辑只有5 步,极简易懂,这也是本文所有实战代码的核心底层逻辑,记牢之后,无论怎么拓展功能,都不会偏离核心:
步骤 1:定义核心状态
- 定义
countDown状态:存储倒计时剩余秒数,初始值为0(默认无倒计时); - 定义
isDisabled状态:存储按钮是否禁用,初始值为false(默认可点击)。
步骤 2:点击「获取验证码」触发倒计时
- 点击按钮时,手动将
countDown设置为目标倒计时秒数(如 60),将isDisabled设置为true(立即禁用按钮); - 触发倒计时的同时,可调用「发送验证码的接口」,实现点击获取验证码的业务逻辑。
步骤 3:开启定时器执行倒计时逻辑
- 通过
useEffect监听countDown状态的变化,当countDown > 0时,开启一个「每秒执行一次」的定时器; - 定时器内部逻辑:每执行一次,将
countDown减 1,实现秒数的实时递减。
步骤 4:倒计时结束自动恢复状态
- 当定时器执行到
countDown === 0时,自动停止定时器; - 同时将
isDisabled恢复为false,按钮重新变为可点击状态,文字切换为「重新发送验证码」。
步骤 5:页面卸载清除定时器(重中之重)
- 通过
useEffect的「返回清理函数」,在页面卸载 / 组件销毁时,强制清除定时器; - 核心作用:防止页面销毁后定时器还在后台运行,导致内存泄漏、应用卡顿,这是新手必踩的坑,也是生产级代码的必备规范。
三、实战核心一:标准版通用验证码倒计时器
import React, { useState, useEffect } from 'react';
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
const SmsCodeCountDown = () => {
const [countDown, setCountDown] = useState(0); // 倒计时剩余秒数,初始0=无倒计时
const [isDisabled, setIsDisabled] = useState(false); // 按钮是否禁用,初始false=可点击
const countDownTime = 60; // 通用验证码倒计时时长,固定60秒,可按需修改
useEffect(() => {
let timer: NodeJS.Timeout | null = null;
if (countDown > 0) {
timer = setInterval(() => {
setCountDown(prev => prev - 1); // 秒数递减
}, 1000);
} else {
// 倒计时结束,恢复按钮可点击状态
setIsDisabled(false);
}
return () => {
if (timer) clearInterval(timer);
};
}, [countDown]);
const handleGetCode = () => {
// 按钮禁用时,禁止执行任何逻辑(双重防点击)
if (isDisabled) return;
// 步骤1:禁用按钮,防止重复点击
setIsDisabled(true);
// 步骤2:启动倒计时,设置为60秒
setCountDown(countDownTime);
// 步骤3:这里写【调用发送验证码的接口】逻辑
console.log('✅ 验证码发送成功,开始倒计时!');
};
const getBtnText = () => {
if (countDown > 0) {
return `${countDown}秒后重新发送`;
} else {
return '获取验证码';
}
};
return (
<View style={styles.container}>
<Text style={styles.title}>鸿蒙端通用验证码倒计时演示</Text>
{/* 验证码输入框占位(可直接对接项目中的输入框) */}
<View style={styles.inputWrap}>
<Text style={styles.inputLabel}>手机号:</Text>
<Text style={styles.inputText}>13800138000</Text>
</View>
{/* 🔥 核心:验证码倒计时按钮 */}
<TouchableOpacity
style={[styles.codeBtn, isDisabled ? styles.codeBtnDisabled : styles.codeBtnActive]}
onPress={handleGetCode}
disabled={isDisabled} // 绑定禁用状态
activeOpacity={0.7} // 鸿蒙端点击透明度反馈,提升交互体验
>
<Text style={[styles.btnText, isDisabled ? styles.btnTextDisabled : styles.btnTextActive]}>
{getBtnText()}
</Text>
</TouchableOpacity>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#f7f8fa',
paddingHorizontal: 20,
},
title: {
fontSize: 20,
color: '#1a1a1a',
fontWeight: '600',
marginBottom: 30,
},
inputWrap: {
width: '90%',
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#ffffff',
padding: 12,
borderRadius: 8,
marginBottom: 20,
borderWidth: 1,
borderColor: '#e0e0e0',
},
inputLabel: {
fontSize: 16,
color: '#333333',
},
inputText: {
fontSize: 16,
color: '#666666',
flex: 1,
marginLeft: 10,
},
// 验证码按钮基础样式
codeBtn: {
width: '90%',
height: 50,
borderRadius: 8,
justifyContent: 'center',
alignItems: 'center',
},
codeBtnActive: {
backgroundColor: '#007DFF',
},
codeBtnDisabled: {
backgroundColor: '#99CCFF',
},
btnText: {
fontSize: 16,
fontWeight: '500',
},
btnTextActive: {
color: '#ffffff',
},
btnTextDisabled: {
color: '#ffffff',
opacity: 0.9,
},
});
export default SmsCodeCountDown;
3.3 鸿蒙端运行效果

四、实战核心二: 可高度自定义的通用倒计时器
import React, { useState, useEffect } from 'react';
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
interface CountDownConfig {
countDownTime: number; // 倒计时时长
btnTextNormal: string;
btnTextCounting: (time: number) => string;
activeColor: string;
disabledColor: string;
}
const CustomCodeCountDown = () => {
const config: CountDownConfig = {
countDownTime: 60,
btnTextNormal: '获取验证码',
btnTextCounting: (time) => `${time}秒 · 重新发送`,
activeColor: '#00C853',
disabledColor: '#CCE5FF',
};
const [countDown, setCountDown] = useState<number>(0);
const [isDisabled, setIsDisabled] = useState<boolean>(false);
useEffect(() => {
let timer: NodeJS.Timeout | null = null;
if (countDown > 0) {
timer = setInterval(() => {
setCountDown(prev => prev - 1); // 函数式更新,避免状态偏差
}, 1000);
} else {
setIsDisabled(false);
}
return () => {
if (timer) clearInterval(timer);
};
}, [countDown]);
// 点击事件
const handleGetCode = () => {
if (isDisabled) return;
setIsDisabled(true);
setCountDown(config.countDownTime);
console.log('✅ 自定义验证码发送成功!');
};
// 动态文案
const getBtnText = () => {
return countDown > 0 ? config.btnTextCounting(countDown) : config.btnTextNormal;
};
return (
<View style={styles.container}>
<Text style={styles.title}>鸿蒙端自定义配置倒计时演示</Text>
<TouchableOpacity
style={[
styles.codeBtn,
{ backgroundColor: isDisabled ? config.disabledColor : config.activeColor }
]}
onPress={handleGetCode}
disabled={isDisabled}
activeOpacity={0.7}
>
<Text style={styles.btnText}>{getBtnText()}</Text>
</TouchableOpacity>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#f7f8fa',
paddingHorizontal: 20,
},
title: {
fontSize: 20,
color: '#1a1a1a',
fontWeight: '600',
marginBottom: 30,
},
codeBtn: {
width: '90%',
height: 50,
borderRadius: 8,
justifyContent: 'center',
alignItems: 'center',
},
btnText: {
fontSize: 16,
fontWeight: '500',
color: '#ffffff',
},
});
export default CustomCodeCountDown;
五、鸿蒙端开发避坑指南
这 4 个坑点是所有 RN 开发者在实现倒计时器时高频踩坑的点,也是面试常问的知识点,全部规避后,你的代码就是「无 BUG、高性能、生产级」的优质代码,零基础也能写出大厂规范的逻辑:
坑点 1:页面卸载后定时器未清除,导致内存泄漏
解决方案:在useEffect中返回清理函数,调用clearInterval(timer)清除定时器,这是本文所有代码都已实现的核心规范,必须遵守!
坑点 2:点击按钮时未做禁用判断,多次点击触发多个定时器,倒计时混乱
解决方案:按钮绑定disabled={isDisabled}属性 + 点击方法内加if(isDisabled) return双重判断,彻底杜绝重复点击,从根源解决定时器混乱问题;
坑点 3:直接修改 state 值,导致倒计时秒数不准
解决方案:修改countDown时,使用「函数式更新」setCountDown(prev => prev - 1),而非直接setCountDown(countDown - 1),确保每次取到的都是最新的秒数,避免异步更新导致的倒计时偏差;
坑点 4:硬编码倒计时时长 / 文案,组件复用性差
解决方案:进阶版中使用配置项统一管理所有可自定义的参数,只需修改配置项即可适配不同场景,无需改动核心逻辑,提升代码复用性。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
更多推荐




所有评论(0)