js实现自定义倒计时器
实现自定义倒计时器的核心逻辑
通过 Date 对象获取时间差,利用 setInterval 动态更新显示。以下是一个基础实现方案:

function startCountdown(targetTime, displayElement) {
const interval = setInterval(() => {
const now = new Date().getTime();
const distance = targetTime - now;
if (distance <= 0) {
clearInterval(interval);
displayElement.textContent = "倒计时结束";
return;
}
const days = Math.floor(distance / (1000 * 60 * 60 * 24));
const hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((distance % (1000 * 60)) / 1000);
displayElement.textContent = `${days}天 ${hours}时 ${minutes}分 ${seconds}秒`;
}, 1000);
}
// 使用示例:倒计时至2023年12月31日
const targetDate = new Date("2023-12-31T00:00:00").getTime();
startCountdown(targetDate, document.getElementById("countdown"));
优化性能的实现方式
使用 requestAnimationFrame 替代 setInterval 避免时间漂移:

function smoothCountdown(targetTime, displayElement) {
function update() {
const now = Date.now();
const distance = targetTime - now;
if (distance <= 0) {
displayElement.textContent = "时间到!";
return;
}
const totalSeconds = Math.floor(distance / 1000);
const days = Math.floor(totalSeconds / 86400);
const hours = Math.floor((totalSeconds % 86400) / 3600);
const minutes = Math.floor((totalSeconds % 3600) / 60);
const seconds = totalSeconds % 60;
displayElement.textContent = `${days}d ${hours}h ${minutes}m ${seconds}s`;
requestAnimationFrame(update);
}
update();
}
添加暂停/继续功能
通过闭包保存计时器状态:
function createCountdownController(targetTime, displayElement) {
let timer = null;
let remainingTime = targetTime - Date.now();
return {
start() {
if (timer) return;
const endTime = Date.now() + remainingTime;
timer = setInterval(() => {
remainingTime = endTime - Date.now();
if (remainingTime <= 0) {
clearInterval(timer);
displayElement.textContent = "完成";
} else {
displayElement.textContent = formatTime(remainingTime);
}
}, 1000);
},
pause() {
clearInterval(timer);
timer = null;
}
};
}
function formatTime(ms) {
// 时间格式化逻辑同上
}
支持回调函数的扩展实现
允许在特定事件触发时执行回调:
function advancedCountdown(options) {
const {
duration,
onUpdate,
onComplete,
interval = 1000
} = options;
let startTime = Date.now();
let expected = startTime + interval;
let timeoutId;
const step = () => {
const elapsed = Date.now() - startTime;
const remaining = Math.max(0, duration - elapsed);
if (remaining <= 0) {
onComplete?.();
return;
}
onUpdate?.(remaining);
const drift = Date.now() - expected;
expected += interval;
timeoutId = setTimeout(step, Math.max(0, interval - drift));
};
timeoutId = setTimeout(step, interval);
return {
stop() {
clearTimeout(timeoutId);
}
};
}
注意事项
- 时区处理:
new Date()使用本地时区,建议用 UTC 时间或明确指定时区 - 内存泄漏:清除不再需要的定时器
- 性能优化:频繁 DOM 操作建议使用文档片段或防抖
- 跨标签页同步:考虑使用
BroadcastChannel或localStorage事件保持多页面同步






