随笔——倒计时
程序员文章站
2022-06-24 18:45:37
<CountDown
format="hh:mm"
startDate={new Date()}
endDate={text}
/* cb={() => {
console.log('倒计时结束');
}} */
/>
**CountDown组件如下:**
import React, { useEffect } from 'react';
import { useImmer } from 'use-immer';
export type CdFormat = 'dd:hh:mm:ss' | 'hh:mm:ss' | 'hh:mm' | 'mm:ss';
interface IProps {
startDate: string | Date;
endDate: string | Date;
format?: CdFormat;
cb?(): void;
}
const stringToDate = (date: string | Date) => {
if (typeof date === 'string') {
// 日期字符串转换为日期对象,并兼容ios
return new Date(Date.parse(date.replace(/-/g, '/')));
}
return date;
};
/**
* 单个数字格式化为两位数, 9 => 09
* @param num
* @returns {string}
*/
const formatTwoDigit = (num: number): string => {
if (num < 10) {
return (Array(2).join('0') + num).slice(-2);
}
return num.toString();
};
const CountDown: React.FC<IProps> = props => {
const [formatDate, setFormatDate] = useImmer<string>('');
const { startDate, endDate, format = 'hh:mm:ss', cb = () => {} } = props;
const [defaultValue, setDefaultValue] = useImmer<string>('');
useEffect(() => {
switch (format) {
case 'dd:hh:mm:ss':
setDefaultValue(() => '00:00:00:00');
break;
case 'hh:mm:ss':
setDefaultValue(() => '00:00:00');
break;
default:
setDefaultValue(() => '00:00');
}
}, [format]);
useEffect(() => {
let interval: any = null;
clearInterval(interval);
const sDate = stringToDate(startDate);
const eDate = stringToDate(endDate);
const startTime = sDate.getTime();
const endTime = eDate.getTime();
// 获取相差的毫秒数
let diffTime = endTime - startTime;
if (diffTime > 0) {
interval = setInterval(() => {
if (diffTime <= 0) {
clearInterval(interval);
cb();
interval = null;
}
let m: string = formatTwoDigit(Math.floor((diffTime / 1000 / 60) % 60));
const s: string = formatTwoDigit(Math.floor((diffTime / 1000) % 60));
let result = '';
// dd:hh:mm:ss
if (/^(d{2}).+(h{2}).+(m{2}).+(s{2})$/.test(format)) {
const d: string = formatTwoDigit(Math.floor(diffTime / 1000 / 60 / 60 / 24));
const h: string = formatTwoDigit(Math.floor((diffTime / 1000 / 60 / 60) % 24));
result = format
.replace(/dd/, d)
.replace(/hh/, h)
.replace(/mm/, m)
.replace(/ss/, s);
setFormatDate(() => result);
}
// hh:mm:ss
else if (/^(h{2}).+(m{2}).+(s{2})$/.test(format)) {
const h = formatTwoDigit(Math.floor(diffTime / 1000 / 60 / 60));
result = format
.replace(/hh/, h)
.replace(/mm/, m)
.replace(/ss/, s);
setFormatDate(() => result);
}
// hh:mm
else if (/^(h{2}).+(m{2})$/.test(format)) {
const h = formatTwoDigit(Math.floor(diffTime / 1000 / 60 / 60));
result = format.replace(/hh/, h).replace(/mm/, m);
setFormatDate(() => result);
}
// mm:ss
else if (/^(m{2}).+(s{2})$/.test(format)) {
m = formatTwoDigit(Math.floor(diffTime / 1000 / 60));
result = format.replace(/mm/, m).replace(/ss/, s);
setFormatDate(() => result);
} else {
clearInterval(interval);
interval = null;
throw new Error('format is error');
}
diffTime -= 1000;
}, 1000);
}
return () => {
clearInterval(interval);
};
}, [startDate, endDate]);
return <div>{formatDate || defaultValue}</div>;
};
export default React.memo(CountDown);
本文地址:https://blog.csdn.net/weixin_44268707/article/details/110233424