为什么JavaScript中多次使用timer计时器仅第一个正常工作?
问题根因
- 原代码使用固定ID定位元素,HTML规范中同一页面ID不能重复,导致后续计时器找不到对应渲染节点
- 全局变量存储截止时间、定时器实例,新增计时器时会覆盖之前的变量,仅最后一个定时器的逻辑能生效
修复方案
1. 调整CSS
把原来ID选择器的样式改成类选择器,其他样式保持不变:
/*time start*/ .timer { font-family: sans-serif; color: #fff; display: inline-block; font-weight: 100; text-align: center; font-size: 16px; margin-right: 40px; /* 多个计时器之间的间距 */ } .timer div { border-radius: 20px; background: #000000f7; display: inline-block; font-family: Oswald; font-size: 52px; font-weight: 400; width: 96px; margin-right: 11px; } .timer .smalltext { color: #ffffff; font-size: 19px; font-family: Poppins; font-weight: 500; display: block; padding: 0; width: auto; margin-top: -11px; } .timer .time-up { /* 把原ID选择器改为类选择器 */ margin: 8px 0 0; text-align: left; font-size: 14px; font-style: normal; color: #000000; font-weight: 500; letter-spacing: 1px; } .delas { display: inline-block; font-size: 23px; padding-right: 31px; } /*time end*/
2. 重写JS逻辑,封装为多实例构造函数
// 计时器构造函数 function CountdownTimer(containerSelector, deadlineStr) { this.container = document.querySelector(containerSelector); if (!this.container) return; this.deadline = new Date(deadlineStr).getTime(); // 仅查找当前计时器容器下的节点,避免和其他计时器冲突 this.dayEl = this.container.querySelector('.day'); this.hourEl = this.container.querySelector('.hour'); this.minuteEl = this.container.querySelector('.minute'); this.secondEl = this.container.querySelector('.second'); this.timeUpEl = this.container.querySelector('.time-up'); // 启动当前计时器 this.start = function() { const _this = this; this.timer = setInterval(function () { const currentTime = new Date().getTime(); const t = _this.deadline - currentTime; const days = Math.floor(t / (1000 * 60 * 60 * 24)); const hours = Math.floor((t % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); const minutes = Math.floor((t % (1000 * 60 * 60)) / (1000 * 60)); const seconds = Math.floor((t % (1000 * 60)) / 1000); _this.dayEl.innerHTML = days; _this.hourEl.innerHTML = hours; _this.minuteEl.innerHTML = minutes; _this.secondEl.innerHTML = seconds; if (t < 1) { clearInterval(_this.timer); _this.timeUpEl.innerHTML = ""; _this.dayEl.innerHTML = "0"; _this.hourEl.innerHTML = "0"; _this.minuteEl.innerHTML = "0"; _this.secondEl.innerHTML = "0"; } }, 1000); } this.start(); } // 初始化多个计时器,传入对应容器选择器和截止时间即可,可无限新增 new CountdownTimer('#timer1', "june 07, 2021, 07:49:25"); new CountdownTimer('#timer2', "july 15, 2024, 12:00:00"); new CountdownTimer('#timer3', "august 20, 2024, 18:30:00");
3. 编写对应HTML结构
<!-- 第一个计时器 --> <div class="timer" id="timer1"> <div><span class="day"></span><span class="smalltext">天</span></div> <span class="delas">:</span> <div><span class="hour"></span><span class="smalltext">时</span></div> <span class="delas">:</span> <div><span class="minute"></span><span class="smalltext">分</span></div> <span class="delas">:</span> <div><span class="second"></span><span class="smalltext">秒</span></div> <div class="time-up"></div> </div> <!-- 第二个计时器 --> <div class="timer" id="timer2"> <div><span class="day"></span><span class="smalltext">天</span></div> <span class="delas">:</span> <div><span class="hour"></span><span class="smalltext">时</span></div> <span class="delas">:</span> <div><span class="minute"></span><span class="smalltext">分</span></div> <span class="delas">:</span> <div><span class="second"></span><span class="smalltext">秒</span></div> <div class="time-up"></div> </div> <!-- 第三个计时器 --> <div class="timer" id="timer3"> <div><span class="day"></span><span class="smalltext">天</span></div> <span class="delas">:</span> <div><span class="hour"></span><span class="smalltext">时</span></div> <span class="delas">:</span> <div><span class="minute"></span><span class="smalltext">分</span></div> <span class="delas">:</span> <div><span class="second"></span><span class="smalltext">秒</span></div> <div class="time-up"></div> </div>
后续需要新增计时器时,只需要新增对应HTML结构,然后在JS初始化代码中加一行new CountdownTimer(对应容器ID, 截止时间字符串)即可。
内容的提问来源于stack exchange,提问作者Alamin
相关产品推荐
相关产品推荐

