同一页面实现多个JavaScript动态价格计数器的调整问题咨询
问题原因
- 你使用的
document.querySelector('.rate')方法默认只会匹配页面中第一个带有rate类的元素,导致所有赛事的计算结果都会写入第一个赛事的价格位置,后续赛事的价格不会更新 - 你在每个赛事对应的script块中,重复使用
const声明了days、DEADLINE等同名变量,const不允许在同一作用域下重复声明同名变量,会触发JS报错,导致后续代码无法执行
解决方案
方案1:最小改动(无需修改现有HTML结构,仅调整每个赛事的script代码)
将每个赛事内部的script代码用立即执行函数包裹,同时修改元素选择逻辑,直接匹配当前代码块对应的价格容器,避免选错元素和变量冲突,示例代码如下:
<!-- 仅展示需要修改的script部分,其他HTML代码保持不变 --> <script type="text/javascript"> // 立即执行函数形成独立局部作用域,不会和其他赛事的变量冲突 (function() { const days = (date) => Math.ceil(date.getTime() / (24 * 60 * 60 * 1000)); // 对应赛事的截止日期保留原有值即可,不同赛事不用改这部分的值 const DEADLINE = days(new Date("2022-01-10")); const START = days(new Date("2021-10-01")); const TODAY = days(new Date()); const res = Math.round(400 - 300 * ((DEADLINE - TODAY) / (DEADLINE - START))); // 直接选中当前script标签前的.rate元素,不会匹配到其他赛事的价格容器 document.currentScript.previousElementSibling.append(`$${res}`); })(); </script>
每个赛事的script都按以上格式修改即可,不需要额外修改rate类名。
方案2:优化版(更适合多赛事维护,后续新增赛事无需重复写JS逻辑)
第一步:全局注入公共计算逻辑
在页面所有赛事代码的上方,或者页面</body>标签之前,仅写入一次公共计算函数:
// 公共价格计算函数,全局仅需定义一次 const calculateEventPrice = (deadlineStr, startDateStr = "2021-10-01", highestPrice = 400, lowestPrice = 100) => { const days = (date) => Math.ceil(date.getTime() / (24 * 60 * 60 * 1000)); const deadline = days(new Date(deadlineStr)); const start = days(new Date(startDateStr)); const today = days(new Date()); return Math.round(highestPrice - (highestPrice - lowestPrice) * ((deadline - today) / (deadline - start))); }
第二步:修改每个赛事的价格容器标签
给每个赛事的rate容器添加自定义属性,存储对应赛事的报名截止日期:
<!-- MLK赛事的价格容器示例 --> Current Price: <div class="rate" data-deadline="2022-01-10" style="display: inline; font-weight:bold;"></div> <!-- PREZ DAY赛事的价格容器示例 --> Current Price: <div class="rate" data-deadline="2022-02-10" style="display: inline; font-weight:bold;"></div>
第三步:添加全局批量更新逻辑
在公共计算函数后面添加批量更新代码,一次性更新所有赛事价格:
document.querySelectorAll('.rate').forEach(rateElement => { const eventDeadline = rateElement.dataset.deadline; const currentPrice = calculateEventPrice(eventDeadline); rateElement.append(`$${currentPrice}`); })
后续新增赛事时,只需要给对应的rate容器加上对应截止日期的data-deadline属性即可,不需要重复写计算逻辑。
内容的提问来源于stack exchange,提问作者Jon Sanders
相关产品推荐
相关产品推荐

