React Native实现验证码倒计时功能

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,
    StyleSheet
} from 'react-native';

function fomatFloat(src, pos) {
    return Math.round(src * Math.pow(10, pos)) / Math.pow(10, pos);
}

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 = 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.setButtonClickDisable(true);
                    } else {
                        this.setButtonClickDisable(false);
                    }
                });
            } else {
                this.setCountdown(-1);
                this.setButtonClickDisable(false);
                this.interval && clearInterval(this.interval);
            }
        }, 1000);
        this.setButtonClickDisable(true);
    }

    setButtonClickDisable(enable) {
        this.setState({
           disabled: enable
        });
    }

    onPress = () => {
        this.setCountdown(120);
        this.startCountDown();
    }

    render() {
        return (
            <TouchableOpacity disabled={this.state.disabled} onPress={this.onPress} style={styles.vcode}>
                {this.state.countdown >= 0 ?
                    <Text style={styles.vcodeText}>
                        {`${this.state.countdown}`}秒
                    </Text> :
                    <Text style={styles.vcodeText}>
                        获取验证码
                    </Text>
                }
            </TouchableOpacity>
        );

    }
}
const styles = StyleSheet.create({
    vcode: {
        borderRadius: 5,
        borderColor: '#ccc',
        borderWidth: 1,
        height:40,
        justifyContent: 'center',
        backgroundColor:'white',
        alignItems: 'center',
        marginLeft: 5
    },
    vcodeText: {
        color: 'rgba(255,165,0,1.0)',
    }
});

export default CountDown;
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值