react倒计时组件 天 时 分 秒
效果如图
倒计时组件CountDown/index.js
/** * 直播未开播倒计时组件 * @autor sjq */ import React, { useState, useEffect, useRef } from 'react' import classNames from 'classnames/bind' import { CheckTime } from '@/utils/countDown' import style from './index.styl' const cx = classNames.bind(style) export const MobileCountDown = (props) => { const { countParams } = props const { day, hour, minute, seconds, leftTime } = countParams // 初始的值 const [timeObj, setTimeObj] = useState({ d: day, h: hour, m: minute, s: seconds, }) const latestCount = useRef(timeObj) const [over, setOver] = useState(false) useEffect(() => { // console.log('==更新的时间', timeObj) latestCount.current = timeObj // 每次更新时间保存 }) // 模拟时钟 const countDownTime = () => { if (over || leftTime < 0) return const latestTimeObj = latestCount.current const isDhms = latestTimeObj.d === 0 && latestTimeObj.h === 0 && latestTimeObj.m === 0 && latestTimeObj.s === 0 const isHms = latestTimeObj.h === 0 && latestTimeObj.m === 0 && latestTimeObj.s === 0 const isMs = latestTimeObj.m === 0 && latestTimeObj.s === 0 const isS = latestTimeObj.s === 0 if (isDhms) setOver(true) else if (isHms) setTimeObj((obj) => { let { d } = obj return { d: d - 1, h: 23, m: 59, s: 59, } }) else if (isMs) setTimeObj((obj) => { let { d, h } = obj return { d, h: h - 1, m: 59, s: 59, } }) else if (isS) setTimeObj((obj) => { let { d, h, m } = obj return { d, h, m: m - 1, s: 59, } }) else setTimeObj((obj) => { let { d, h, m, s } = obj return { d, h, m, s: s - 1, } }) } useEffect(() => { let timeCard = setInterval(countDownTime, 1000) return () => { clearInterval(timeCard) } }) return ( <> { !over && ( <div className={`${cx('count-down')}`}> <div className={cx('count-down-contain')}> <div className={cx('count-down-text')}>距直播开始</div> <div className={cx('count-down-card')}> <div className={cx('count-down-diamond count-down-hour')}> {CheckTime(timeObj.d)} </div> <div className={cx('count-down-semi count-down-semicolon')}> 天 </div> <div className={cx('count-down-diamond count-down-hour')}> {CheckTime(timeObj.h)} </div> <div className={cx('count-down-semi count-down-semicolon')}> 时 </div> <div className={cx('count-down-diamond count-down-minute')}> {CheckTime(timeObj.m)} </div> <div className={cx('count-down-semi count-down-semicolon')}> 分 </div> <div className={cx('count-down-diamond count-down-second')}> {CheckTime(timeObj.s)} </div> <div className={cx('count-down-semi count-down-semicolon')}> 秒 </div> </div> </div> </div> )} </> ) }
父组件
....
import { initTime } from '@/utils/countDown'
....
const MPlayer = (props) => { const [countPlayStatus, setCountPlayStatus] = useState('') const [timeParams, setTimeParams] = useState({}) useEffect(() => { const { server_time, content } = courseContent || {} if (courseContent&&server_time&&content) { const { start_time, status } = content[0] || {}
// 重点可以看一下这一块 传入的开始和结束时间 const initCount = initTime({ type: 's', startTime: start_time, serverTime: server_time, }) setCountPlayStatus(status) setTimeParams(initCount)
} }, []) return ( <div className={cx( isTransverse && type === 'rtc' ? 'player-transverse-wrapper' : 'player-wrapper' )} > {/* 未开播的时候显示倒计时 未开播而且没有流的时候 显示倒计时 前面的很多逻辑. demo的时候可去掉,只显示组件即可*/} {countPlayStatus=== NO_START && liveStatus !== RUNNING && liveStatus !== FINISHED && timeParams.leftTime > 0 && ( <MobileCountDown countParams={timeParams} /> )} </div> ) } .....
const mapStateToProps = (state) => ({
isTransverse: state.system.isTransverse,
liveMsgTract: state.im.liveMsgTract
})
....export default filterComp(Player, connect(mapStateToProps)(MPlayer))
.......
关于倒计时提取的方法utils/countDown.js
/** * 倒计时公用方法抽取 * @author sjq */ // 向下取整 export function ChangeNumFloor(num) { return Math.floor(num) } // 后端获取字段转为天:小时:分钟:秒 export function initTime({ type = 'ms', startTime = 0, serverTime = 0 } = {}) { const now = type === 's' ? Number(serverTime) * 1000 : serverTime // 1641564283 后端传过来的字段是s这里做了一下兼容如果是ms也支持 const getStartTime = startTime.replace(/-/g, '/') // 预设开课时间 后端字段接口里面取字段时间格式 "2022-01-14 09:00:00" 转换成2022/01/14 09:00:00 否则手机时间无效时间 const endDate = new Date(getStartTime) const end = endDate.getTime() const leftTime = end - now const day = ChangeNumFloor(leftTime / 1000 / 60 / 60 / 24) const hour = ChangeNumFloor((leftTime / 1000 / 60 / 60) % 24) const minute = ChangeNumFloor((leftTime / 1000 / 60) % 60) const seconds = ChangeNumFloor((leftTime / 1000) % 60) return { day, hour, minute, seconds, leftTime, } } // 天:小时:分钟:秒 单个数字需要补0 export function CheckTime(i) { return i.toString().padStart(2, '0') }
--------------有问题或者更优方案欢迎留言讨论------------------