一、实现效果

假如后端返了两个数据:
当前时间的13位时间戳currentTimestamp、秒抢时间的13位时间戳seckillTimestamp,想实现“距开始秒抢”的倒计时,即:秒抢时间与当前时间之间的时间差以“时分秒”的形式进行倒计时,如下动图:

二、实现方式
第一步、封装方法——js将时间戳转换成“时分秒”
【注意】:是“时分秒”,不是 “天时分秒”哦~ (二者写法是有区别滴哦)
utils.js:
/**
1、js获取 倒计时 时分秒
通过时间戳的方式来
let h = Math.trunc(dec / 3600); // 时
let m = Math.trunc(dec % 3600 / 60); // 分
let s = Math.trunc(dec % 3600 % 60); // 秒
2、参数分析:
@param {Num} inputTime: 需要转换成 时分秒 的 13位时间戳
@param {Boolean} isPop: 便于实现两种返回结果:true -> `${h}小时${m}分${s}秒` ; false -> 包含时分秒的finalDateObj对象
*/
function timestampFormatter(inputTime, isPop = false) {
// 最终时间结果对象
const finalDateObj = {
h: null, // 小时
m: null, // 分钟
s: null, // 秒
}
// 剩余时间总的毫秒数 除以 1000 变为总秒数(时间戳为13位 需要除以1000,为10位 则不需要)
let dec = inputTime / 1000;
if (dec <= 0) {
dec = 0;
}
// 得到小时 格式化成前缀加零的样式
let h = Math.trunc(dec / 3600);
h = h < 10 ? '0' + h : h;
// 得到分钟 格式化成前缀加零的样式
let m = Math.trunc(dec % 3600 / 60);
m = m < 10 ? '0' + m : m;
// 得到秒 格式化成前缀加零的样式
let s = Math.trunc(dec % 3600 % 60);
s = s < 10 ? '0' + s : s;
finalDateObj.h = h;
finalDateObj.m = m;
finalDateObj.s = s;
return isPop ? `${h}小时${m}分${s}秒` : finalDateObj;
}
第二步、实现“时分秒”的倒计时
![]()
实现思路同我的另外一篇博文,相比其代码,只是有两处区别,如下:
countDownComponent.jsx
这是含倒计时的子组件。
1、倒计时初始值
参考项目代码:
// 1、初始化state
state = {
canCountDown: true, // 判断是否开启定时器
finalDate: '00天00小时00分', // 倒计时初始值
}
现项目代码:
// 1、初始化state
state = {
canCountDown: true, // 判断是否开启定时器
h1: '0', // 倒计时初始值-时
h2: '0', // 倒计时初始值-时
m1: '0', // 倒计时初始值-分
m2: '0', // 倒计时初始值-分
s1: '0', // 倒计时初始值-秒
s2: '0', // 倒计时初始值-秒
}
2、获取到倒计时最终值【位于方法updateTime里】
参考项目代码:
/** 调用上面封装的方法timestampFormatter,计算到倒计时的展示结果,并state赋值,方便html里进行展示 */
const result = timestampFormatter(countDownTimestamp, true);
this.setState({
finalDate: result,
})
现项目代码:
/** 调用上面封装的方法timestampFormatter,计算到倒计时的展示结果,并state赋值,方便html里进行展示 */
const _h = timestampFormatter(countDownTime).h + '';
const _m = timestampFormatter(countDownTime).m + '';
const _s = timestampFormatter(countDownTime).s + '';
this.setState({
h1: _h.slice(0, 1),
h2: _h.slice(-1),
m1: _m.slice(0, 1),
m2: _m.slice(-1),
s1: _s.slice(0, 1),
s2: _s.slice(-1),
})
第三步、HTML渲染
render(){
const { h1, h2, m1, m2, s1, s2 } = this.state;
return(
<div __examplenotes="倒计时" className="countDown">
<span __examplenotes="倒计时背景" className="countDownBg"></span>
<span __examplenotes="时" className="commonTime hour1">{h1}</span>
<span __examplenotes="时" className="commonTime hour2">{h2}</span>
<span __examplenotes="分" className="commonTime minute1">{m1}</span>
<span __examplenotes="分" className="commonTime minute2">{m2}</span>
<span __examplenotes="秒" className="commonTime second1">{s1}</span>
<span __examplenotes="秒" className="commonTime second2">{s2}</span>
</div>
)
}
三、坑?
如上结果动图可知:我们实现的是一个可以
tab切换的倒计时项目。
- 实现思路:把倒计时相关的部分封装成一个组件,随之渲染页面。
- 坑?:当
tab1里的第一条数据的倒计时小于0时,tab2里的第一条数据的倒计时 自动归置为0(即使 其并非为0);当tab1里的第二条数据的倒计时小于0时,tab2里的第二条数据的倒计时 自动归置为0(即使 其并非为0);依次类推。。。- 分析原因:原来是因为我们在更新倒计时时间时定义了如下代码【当倒计时小于
0时,定时器被关闭了】,如下图所示:- 解决方法:我们需要在切换
tab时,判断组件的定时器timer是不是null,如果是null且countDownTimestamp大于0,调下funTimer(),重新开启定时器,代码如下:【需结合我的另外一篇博文一起看哦~】
countDownComponent.jsx
这是含倒计时的子组件。
componentDidMount() {
// 发送事件"startTimer"
document.addEventListener("startTimer", this.startTimer, this);
}
componentWillUnmount() {
// 移除事件"startTimer"
document.removeEventListener("startTimer", this.startTimer, this);
}
// 判断组件的定时器timer是不是null,如果是null且countDown大于0,调下funTimer()
startTimer = () => {
/** seckillTimestamp:秒杀开始时间的时间戳,currentTimestamp:当前时间的时间戳 */
const seckillTimestamp = 1664280000000; // 秒杀开始时间【实际情况时 由后台返回,这儿写死只是做个测试】
/** 计算倒计时的展示结果,并return值,方便html里进行展示 */
const countDownTimestamp = seckillTimestamp * 1 - this.currentTimestamp * 1; // 计算得到 倒计时 的时间戳
if (this.timer == null && countDownTimestamp > 0) {
this.FunTimer();
}
}
homePage.jsx
这是调用倒计时子组件的首页
// 标题tab切换按钮 - 0->今日秒抢, 1->明日秒抢
switchTitle = _throttle(async (index) => {
// 调用组件CountDownComponent里的方法
document.dispatchEvent(new CustomEvent("startTimer", {}));
}, 1000)

版权声明:本文为weixin_48850734原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。
