← 返回目录

15. 秒杀倒计时综合实战

把前面学的串起来:setInterval 每秒刷新 + 时间戳相减算剩余 + formatTime 格式化 + 归零 clearInterval。这是定时器最典型的真实业务。

15.1 互动演示(活动结束 = 当前时间 + 2 分钟)

0
0
0
0
点"开始倒计时"观察每秒刷新;归零后显示"活动已结束"并自动清除定时器。

15.2 知识点讲解

① 核心思路:为什么用"时间戳相减"而不是"每秒减 1"?

如果写成 count--,浏览器切到后台会暂停定时器,回来时数字就"慢"了。正确做法:记录结束时间戳,每秒用"结束时间 − 当前时间"现算剩余——后台回来也能立刻算对。

// 1. 先定好结束时刻:现在往后 2 小时(用毫秒时间戳算)
let endTime = Date.now() + 2 * 60 * 60 * 1000;

// 2. 每秒现算一次还剩多少秒(结束时刻 − 现在)
let remain = Math.floor((endTime - Date.now()) / 1000);
// Date.now() 是当前时间戳(毫秒),两个一减再除 1000 就是秒

// 3. 减到 0 就停
if (remain <= 0) {
  clearInterval(timer); // 把闹钟关了
  // 页面上显示"活动已结束"
}

Date.now() 返回毫秒时间戳;Math.floor 向下取整(比如剩 99.7 秒显示 99 秒)。

② formatTime:总秒数 → 天时分秒(% 取余逐行讲)

function formatTime(seconds) {
  // 一天有 86400 秒:先整除出"凑满了几天"
  let day = Math.floor(seconds / 86400);

  // % 是取余数:去掉整天后还剩多少秒,再除 3600 得小时
  let hour = Math.floor(seconds % 86400 / 3600);

  // 再去掉整天和整小时,剩下的除 60 得分钟
  let minute = Math.floor(seconds % 3600 / 60);

  // 最后剩下的零头就是秒
  let sec = seconds % 60;

  return day + "天" + hour + "时" + minute + "分" + sec + "秒";
}

口诀:先整除大的(天)、再用 % 取余算小的(时→分→秒)。比如 90061 秒 = 1 天 1 时 1 分 1 秒。

③ 完整倒计时流程(5 步闭环)

let timer = null; // 把闹钟编号先放空着

function start() {
  // 第 1 步:定好结束时刻 = 现在往后 2 分钟
  let endTime = Date.now() + 2 * 60 * 1000;

  // 第 2 步:定个每秒响一次的循环闹钟
  timer = setInterval(function () {
    // 第 3 步:每秒现算还剩多少秒
    let remain = Math.floor((endTime - Date.now()) / 1000);

    // 第 4 步:减到 0 了,关闹钟 + 显示结束
    if (remain <= 0) {
      clearInterval(timer); // 先关闹钟
      show("活动已结束");
      return; // 后面的就别跑了
    }

    // 第 5 步:把秒数拆成天时分秒,显示到页面上
    show(formatTime(remain));
  }, 1000);
}

归零分支里先 clearInterval 再 return,避免负数继续显示。作业要求"封装 formatTime"就是这么来的。

一句话记住:结束时间戳相减算剩余秒数 → formatTime(整除天、取余算时分秒)→ setInterval 每秒刷新 → 归零 clearInterval