用React实现一个秒杀倒计时组件

复制代码
先声明一个补0的函数
复制代码
// 先声明一个补0的函数
function formate(time: number): string {
  return `${time < 10 ? "0" : ""}${time}`;
}
复制代码
定义最终返回的数据结构
复制代码
export interface TimeInfo {
  /** 天 */
  day: number;
  /** 小时 */
  hours: number;
  /** 补零后的小时 */
  hoursStr: string;
  /** 分钟 */
  minutes: number;
  /** 补零后的分 */
  minutesStr: string;
  /** 秒 */
  seconds: number;
  /** 补零后的秒 */
  secondsStr: string;
  /** 毫秒 */
  milliseconds?: number;
  /** 补零后的毫秒 */
  millisecondsStr?: string;
  /** 倒计时状态 pending-初始化状态 runing-进行中 end-已结束 */
  status: "pending" | "runing" | "end";
}
复制代码
工具方法——清除倒计时数据信息:
复制代码
function clearCountdownInfo(showMillisecond = false, status?: TimeInfo["status"]): TimeInfo {
  const timeInfo: TimeInfo = {
    day: 0,
    hours: 0,
    hoursStr: "00",
    minutes: 0,
    minutesStr: "00",
    seconds: 0,
    secondsStr: "00",
    status: status || "end",
  };

  if (showMillisecond) {
    timeInfo.milliseconds = 0;
    timeInfo.millisecondsStr = "0";
  }

  return timeInfo;
}
复制代码
关键工具方法——计算倒计时返回的数据信息:
复制代码
function computeCountdownInfo(
  remainTime: number,
  showMillisecond = false
): TimeInfo {
  // 剩余时间小于说明结束,直接清空
  if (remainTime < 0) {
    return clearCountdownInfo(showMillisecond);
  }

  // 这里用了一个比较笨的方法,一个个进行计算,后续可以优化试试看
  const day = Math.floor(remainTime / (24 * 60 * 60));
  const hours = Math.floor((remainTime / (60 * 60)) % 24);
  const hoursStr = formate(hours);
  const minutes = Math.floor((remainTime / 60) % 60);
  const minutesStr = formate(minutes);
  const seconds = Math.floor(remainTime % 60);
  const secondsStr = formate(seconds);

  // 组合成需要返回的时间信息
  const timeInfo: TimeInfo = {
    day,
    hours,
    hoursStr,
    minutes,
    minutesStr,
    seconds,
    secondsStr,
    status: "runing",
  };

  // 需要显示毫秒逻辑处理
  if (showMillisecond) {
    const milliseconds = Math.floor(remainTime * 1000);
    // 只取首位
    const millisecondsStr = String(milliseconds).slice(-3);
    timeInfo.milliseconds = milliseconds;
    timeInfo.millisecondsStr = millisecondsStr;
  }

  return timeInfo;
}

定义函数:

复制代码
interface CountDownOptions {
  showMillisecond: boolean
  deadlineTime: any
}

function computeRemainTime(deadlineTime: number) {
  // 当前时间
  const nowTime = Date.now();
  // 截止时间 - 当前时间 = 剩余时间
  const remainTime = (deadlineTime - nowTime) / 1000;
  return remainTime;
}
复制代码
核心逻辑 —— useCountdown hook 组件:
复制代码
export const useCountdown = (options: CountDownOptions) => {
  // 首次初始化数据,显示清除的数据
  const [timeInfo, setTimeInfo] = useState<TimeInfo>(
    clearCountdownInfo(options.showMillisecond, "pending")
  );
  useEffect(() => {
    let timer = 0;

    function countdown() {
      const remainTime = computeRemainTime(options.deadlineTime);
      // 剩余时间大于 0 才开始倒计时
      if (remainTime > 0) {
        // 未结束时直接定时下一次在执行判断 countdown
        timer = setTimeout(
          countdown,
          options.showMillisecond ? 100 : 1000 // 毫秒级则修改定时器时间
        );
      }
      const data = computeCountdownInfo(remainTime, options.showMillisecond);
      setTimeInfo(data);
    }

    // 开始倒计时
    countdown();

    return () => {
      // 清除定时器
      timer && clearTimeout(timer);
    };
  }, [options.deadlineTime, options.showMillisecond]);

  return timeInfo;
};

看一下在组件中的应用:

复制代码
import { Layout, Row, Typography } from 'antd';
import React from 'react';
import { useCountdown } from './CountDown';

interface Props {
  name: string;
}

const Guide: React.FC<Props> = (props) => {

  // deadlineTime这个时间在传的时候要比当前的时间往后,要不然效果出不来,这里注意一点
  const {
    day,
    hoursStr,
    minutesStr,
    secondsStr,
  } = useCountdown({showMillisecond: false, deadlineTime: 1743907169000})

  return (
    <Layout>
      <div style={{color: 'red', fontSize: 28, marginBottom: 24}}>
        {day}天:
        {hoursStr}时:
        {minutesStr}分:
        {secondsStr}秒
      </div>
    </Layout>
  );
};

export default Guide;

再来看一下页面的效果吧:

相关推荐
小小小小宇5 小时前
虚拟列表兼容老DOM操作
前端
悦悦子a啊5 小时前
Python之--基本知识
开发语言·前端·python
安全系统学习6 小时前
系统安全之大模型案例分析
前端·安全·web安全·网络安全·xss
涛哥码咖6 小时前
chrome安装AXURE插件后无效
前端·chrome·axure
OEC小胖胖6 小时前
告别 undefined is not a function:TypeScript 前端开发优势与实践指南
前端·javascript·typescript·web
行云&流水7 小时前
Vue3 Lifecycle Hooks
前端·javascript·vue.js
Sally璐璐7 小时前
零基础学HTML和CSS:网页设计入门
前端·css
老虎06277 小时前
JavaWeb(苍穹外卖)--学习笔记04(前端:HTML,CSS,JavaScript)
前端·javascript·css·笔记·学习·html
三水气象台7 小时前
用户中心Vue3网页开发(1.0版)
javascript·css·vue.js·typescript·前端框架·html·anti-design-vue
灿灿121387 小时前
CSS 文字浮雕效果:巧用 text-shadow 实现 3D 立体文字
前端·css