React Native实现验证码倒计时功能
实现倒计时功能使用的是核心方法 setInterval,setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。
startCountDown() {
this.interval = setInterval(() => { this.setState({ countdown: this.getCountdown() - 1 }); },1000); }
当 App 切换至后台之后,setInterval 将不会执行,而当 App 从后台切换至前台时,setInterval 将继续执行,所以对于切换至后台的情况需要监听 App 状态,记录变化的时间。React Native 提供了 AppState 监听 App 状态改变,AppState 一共有三种状态,包括以下三种。
- active - 应用正在前台运行
- background - 应用正在后台运行。用户既可能在别的应用中,也可能在桌面
- inactive - 这是一个过渡状态,不会在正常的 React Native 应用中出现
componentDidMount() {
AppState.addEventListener('change',this._handleAppStateChange);
}
componentWillUnmount() {
AppState.removeEventListener('change',this._handleAppStateChange);
this.interval && clearInterval(this.interval);
}
_handleAppStateChange = (nextAppState) => {
if (this.state.appState === 'active' && nextAppState.match(/inactive|background/)) {
this.backgroundTime = new Date().getTime() / 1000;
}
if (this.state.appState.match(/inactive|background/) && nextAppState === 'active') {
this.backgroundTime = utils.fomatFloat(new Date().getTime() / 1000 - this.backgroundTime,0);
}
this.setState({appState: nextAppState});
}
最后完整代码
import React,{
PureComponent,} from 'react';
import {
TouchableOpacity,Text,AppState
} from 'react-native';
import * as utils from '../utils';
class CountDown extends PureComponent {
constructor(props) {
super(props);
this.state = {
appState: AppState.currentState,countdown: -1,disabled: false
};
this.backgroundTime = 0;
}
componentDidMount() {
AppState.addEventListener('change',this._handleAppStateChange);
}
componentWillUnmount() {
AppState.removeEventListener('change',this._handleAppStateChange);
this.interval && clearInterval(this.interval);
}
_handleAppStateChange = (nextAppState) => {
if (this.state.appState === 'active' && nextAppState.match(/inactive|background/)) {
this.backgroundTime = new Date().getTime() / 1000;
}
if (this.state.appState.match(/inactive|background/) && nextAppState === 'active') {
this.backgroundTime = utils.fomatFloat(new Date().getTime() / 1000 - this.backgroundTime,0);
}
this.setState({appState: nextAppState});
}
setCountdown(countdown) {
this.setState({
countdown: countdown
});
}
getCountdown() {
return this.state.countdown;
}
startCountDown() {
this.interval = setInterval(() => { if (this.backgroundTime < this.getCountdown()) { this.setState({ countdown: this.getCountdown() - this.backgroundTime - 1 },()=>{ this.backgroundTime = 0; if (this.getCountdown() < 0) { this.interval && clearInterval(this.interval); } if (this.getCountdown() >= 0) { this.setState({ disabled: true }); } else { this.setState({ disabled: false }); } }); } else { this.setCountdown(-1); this.setState({ disabled: false }); this.interval && clearInterval(this.interval); } },1000); this.setState({ disabled: true }); } render() { const { onPress,style,vcodeTextStyle } = this.props; return ( <TouchableOpacity disabled={this.state.disabled} onPress={onPress} style={style}> {this.state.countdown >= 0 ? <Text style={vcodeTextStyle}> {`${this.state.countdown}`}秒 </Text> : <Text style={vcodeTextStyle}> 获取验证码 </Text> } </TouchableOpacity> ); } } export default CountDown;
其中 utils.fomatFloat 是截取小数点后几位的一个方法
//保留小数点后几位
export function fomatFloat(src,pos) {
return Math.round(src * Math.pow(10,pos)) / Math.pow(10,pos);
}