• 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')
    }

    --------------有问题或者更优方案欢迎留言讨论------------------

  • 相关阅读:
    python入门 类的继承和聚合(五)
    如何快速找到多个字典中的公共键(1.4)
    python输入输出(二)
    python入门 集合(四)
    LOJ 3093: 洛谷 P5323: 「BJOI2019」光线
    LOJ 3049: 洛谷 P5284: 「十二省联考 2019」字符串问题
    【比赛游记】FJOI2019瞎打记
    ICPC World Finals 2019 题解
    LOJ 3043: 洛谷 P5280: 「ZJOI2019」线段树
    LOJ 2483: 洛谷 P4655: 「CEOI2017」Building Bridges
  • 原文地址:https://www.cnblogs.com/pikachuworld/p/15904711.html
Copyright © 2020-2023  润新知