本文共 7282 字,大约阅读时间需要 24 分钟。
最近研究了一下倒计时,网上有不少第三方开源库,不过试了试,有的并不好用,写法也停留在ES5上,而我写的demo使用的是0.45版本的RN,改起来很是麻烦。于是就参考实现了一下倒计时按钮,效果还不错~ http://www.jianshu.com/p/f5925a95c01b
我们将要使其样式、提示文字及显示方式可以自定义。那就要将文字样式,提示文字(包括显示的时间数字,时间单位等)都定义为组件属性,可以由调用者灵活定义。
首先用户输入一个结束时间,我们需要声明一个state,再写一个计时器,我们每隔1s就通过输入的结束时间和当前时间计算出时间差,再通过算法将时间差计算成xx天xx时xx分xx秒的格式,更改state的值,通过state的更改及判断计算结果,在render()方法中控制时间的显示及更新。
新建countDown.js
/** * Created by sybil052 on 2017/6/22. */import React, { Component, PropTypes,} from 'react';import { StyleSheet, View, Text,} from 'react-native';const styles = StyleSheet.create({ text: { fontSize: 30, color: '#FFF', marginLeft: 7, }, container: { flexDirection: 'row', }, // 时间文字 defaultTime: { paddingHorizontal: 3, backgroundColor: '#555555', fontSize: 12, color: '#fff', marginHorizontal: 3, borderRadius: 2, }, // 冒号 defaultColon: { fontSize: 12, color: '#555555' }, // 提示 defaultTip: { fontSize: 12, color: '#555555', }});class CountDown extends Component { static displayName = 'Simple countDown'; // 属性 static propTypes = { tip: PropTypes.string, date: PropTypes.string, days: PropTypes.objectOf(PropTypes.string), hours: PropTypes.string, mins: PropTypes.string, segs: PropTypes.string, onEnd: PropTypes.func, containerStyle: View.propTypes.style, daysStyle: Text.propTypes.style, hoursStyle: Text.propTypes.style, minsStyle: Text.propTypes.style, secsStyle: Text.propTypes.style, firstColonStyle: Text.propTypes.style, secondColonStyle: Text.propTypes.style, tipStyle: Text.propTypes.style, }; // 默认属性 static defaultProps = { date: new Date(), days: { plural: '天', singular: '天', }, hours: ':', mins: ':', segs: ':', tip: '', onEnd: () => {}, containerStyle: styles.container, // container 的style daysStyle: styles.defaultTime, // 天数 字体的style hoursStyle: styles.defaultTime, // 小时 字体的style minsStyle: styles.defaultTime, // 分钟 字体的style secsStyle: styles.defaultTime, // 秒数 字体的style firstColonStyle: styles.defaultColon, // 从左向右 第一个冒号 字体的style secondColonStyle: styles.defaultColon, // 从左向右 第2个冒号 字体的style tipStyle: styles.defaultTip, // 提示字体style }; state = { days: 0, hours: 0, min: 0, sec: 0, }; componentDidMount() { this.interval = setInterval(()=> { const date = this.getDateData(this.props.date); if (date) { this.setState(date); } else { this.stop(); this.props.onEnd(); } }, 1000); } componentWillMount() { const date = this.getDateData(this.props.date); if (date) { this.setState(date); } } componentWillUnmount() { this.stop(); } getDateData(endDate) { endDate = endDate.replace(/-/g,"/"); console.log('end',new Date(endDate)); console.log('now',new Date); // console.log('end===',Date.parse(new Date(endDate))); // console.log('now===',Date.parse(new Date)); let diff = (Date.parse(new Date(endDate)) - Date.parse(new Date)) / 1000; if (diff <= 0) { return false; } // console.log('===========',diff); const timeLeft = { years: 0, days: 0, hours: 0, min: 0, sec: 0, millisec: 0, }; if (diff >= (365.25 * 86400)) { timeLeft.years = Math.floor(diff / (365.25 * 86400)); diff -= timeLeft.years * 365.25 * 86400; } if (diff >= 86400) { timeLeft.days = Math.floor(diff / 86400); diff -= timeLeft.days * 86400; } if (diff >= 3600) { timeLeft.hours = Math.floor(diff / 3600); diff -= timeLeft.hours * 3600; } if (diff >= 60) { timeLeft.min = Math.floor(diff / 60); diff -= timeLeft.min * 60; } timeLeft.sec = diff; return timeLeft; } render() { const countDown = this.state; let days; if (countDown.days === 1) { days = this.props.days.singular; } else { days = this.props.days.plural; } return ({ this.props.tip ? ); } stop() { clearInterval(this.interval); } // 数字前面补0 leadingZeros(num, length = null) { let length_ = length; let num_ = num; if (length_ === null) { length_ = 2; } num_ = String(num_); while (num_.length < length_) { num_ = '0' + num_; } return num_; }}export default CountDown;{this.props.tip} : null} { (countDown.days > 0) ?{ this.leadingZeros(countDown.days)+days} : null} { countDown.hours > 0 ?{ this.leadingZeros(countDown.hours)} : null} { countDown.hours > 0 ?{this.props.hours} : null}{this.leadingZeros(countDown.min)} {this.props.mins} {this.leadingZeros(countDown.sec)} {this.props.segs}
来说下我们要实现的效果,传入一个结束时间,开始倒计时,倒计时中,抢单按钮可以点击,当倒计时结束,按钮置灰且不可点击。
新建demo.js
/** * Created by sybil052 on 2017/6/19. */import React, {Component} from 'react';import {connect} from 'react-redux';import { View, Text, StyleSheet, TouchableOpacity,} from 'react-native';import CountDown from '../../components/countDown';class Demo extends Component { constructor(props) { super(props); this.state={ isEnd: false } } componentDidMount() { } render() { return (); }}const styles =StyleSheet.create({ container: { flex: 1, backgroundColor: 'white' }, //时间文字 time: { paddingHorizontal: 2, fontSize: 13, color: 'white', textAlign: 'center', lineHeight: 17, }, //冒号 colon: { fontSize: 13, color:'white', textAlign: 'center', lineHeight: 17, }, tip:{ color: 'white', textAlign: 'center', fontSize: 13, lineHeight: 17 }});function mapStateToProps(state){ return {};}function mapDispatchToProps (dispatch){ return {};}export default connect(mapStateToProps, mapDispatchToProps)(Demo); { alert('抢单'); }}> 抢单 { this.setState({ isEnd: true }) }} />
好了,自定义的倒计时按钮就写好了~希望对你们有所帮助!!!
转载地址:http://dyrni.baihongyu.com/