如何为支持动态日期的JS倒计时同步显示对应事件标题
动态赛事倒计时标题同步实现
思路选型
优先用「把事件标题存在现有日程数组里」的方案。比起单独写switch存标题的方式,这个方案不用额外维护标题和索引的对应关系,之后加新赛事只要往日程数组里加一行配置就行,不会出现分支逻辑和数组内容对不上的情况,改起来更省事。
现有代码的问题
- 重复遍历
schedule数组2次,会触发2次initializeClock调用,同时启动多个倒计时计时器,导致页面倒计时数字刷新错乱 - 循环外部取到的变量
i是for循环跑完全程后的全局残留值,根本不是当前匹配到的赛事对应的索引,后面switch语句拿到的索引值完全不准 - 没有把匹配到的赛事标题同步写到DOM节点里,页面的赛事标题展示区域一直是空的
修改后可直接运行的完整代码
<div> Next Race<br> <span class="nextRace"></span> </div> <div id="clockdiv"> <span class="race title"></span> Days: <span class="days"></span><br> Hours: <span class="hours"></span><br> Minutes: <span class="minutes"></span><br> Seconds: <span class="seconds"></span> </div>
const schedule = [ ['Feb 25 2021', 'Feb 9 2021', "race 1"], ['Feb 9 2021', 'Apr 20 2021', "race 2"], ['Apr 20 2022', 'Jul 25 2023', "race 3"] ]; function getTimeRemaining(endtime) { const total = Date.parse(endtime) - Date.parse(new Date()); const seconds = Math.floor((total / 1000) % 60); const minutes = Math.floor((total / 1000 / 60) % 60); const hours = Math.floor((total / (1000 * 60 * 60)) % 24); const days = Math.floor(total / (1000 * 60 * 60 * 24)); return { total, days, hours, minutes, seconds }; } function initializeClock(id, endtime, raceTitle) { const clock = document.getElementById(id); const daysSpan = clock.querySelector('.days'); const hoursSpan = clock.querySelector('.hours'); const minutesSpan = clock.querySelector('.minutes'); const secondsSpan = clock.querySelector('.seconds'); // 同步更新两处标题展示 document.querySelector('.nextRace').innerHTML = raceTitle; clock.querySelector('.race.title').innerHTML = raceTitle; function updateClock() { const t = getTimeRemaining(endtime); daysSpan.innerHTML = t.days; hoursSpan.innerHTML = ('0' + t.hours).slice(-2); minutesSpan.innerHTML = ('0' + t.minutes).slice(-2); secondsSpan.innerHTML = ('0' + t.seconds).slice(-2); if (t.total <= 0) clearInterval(timeinterval); } updateClock(); const timeinterval = setInterval(updateClock, 1000); } // 合并重复的遍历逻辑,只做一次时间匹配 for (let i = 0; i < schedule.length; i++) { const [startDate, endDate, raceTitle] = schedule[i]; const startMs = Date.parse(startDate); const endMs = Date.parse(endDate); const currentMs = Date.parse(new Date()); // 匹配当前时间落在有效区间内的赛事 if (endMs > currentMs && currentMs >= startMs) { initializeClock('clockdiv', endDate, raceTitle); } }
调整说明
- 删掉了原来冗余的switch语句,因为标题信息已经存在日程数组的第三个字段里,不需要硬编码映射
- 把原来两次重复的数组遍历合并成一次,避免多个计时器同时启动造成的数字错乱
- 给
initializeClock函数加了raceTitle入参,匹配到对应赛事时,直接读取数组里存的标题值,同步更新两个展示位置的内容 - 把原来循环里的
var换成let,避免变量泄露到全局作用域造成取值异常
内容的提问来源于stack exchange,提问作者mike
相关产品推荐
相关产品推荐

