基于Vanilla JS变量状态切换展示数据的实现问题
解决时间追踪仪表盘的时间框架切换问题(仅加载一次数据)
你当前代码的核心问题是:数据渲染逻辑只在页面加载时执行了一次,点击daily/weekly/monthly按钮时,仅更新了timeframe变量和按钮样式,但没有触发新的数据渲染。要实现仅加载一次数据并切换展示,需要把渲染逻辑抽离成可复用的函数,在每次切换时调用。
关键改动点
- 将获取到的
data存储为全局变量,确保页面加载后数据可被后续渲染逻辑访问 - 提取
renderData独立函数,接收当前timeframe作为参数,负责更新页面数据 - 在按钮点击事件中,更新
timeframe后调用renderData函数 - 优化DOM元素获取方式,用循环批量获取,减少重复代码
修改后的完整代码
// 批量获取DOM元素,替代逐个getElementById const getElements = (prefix, count) => { return Array.from({ length: count }, (_, i) => document.getElementById(`${prefix}-${i + 1}`) ); }; const titlesFromDOM = getElements("title", 6); const currentFromDOM = getElements("time", 6); const lastFromDOM = getElements("last", 6); const daily = document.getElementById("daily"); const weekly = document.getElementById("weekly"); const monthly = document.getElementById("monthly"); let timeframe; let data; // 全局存储数据,仅加载一次 const timeframes = [ { element: daily, name: "Daily" }, { element: weekly, name: "Weekly" }, { element: monthly, name: "Monthly" }, ]; timeframes.forEach((item) => { item.element.addEventListener("click", () => { timeframe = item.name; checkTimeframe(); renderData(); // 切换后调用渲染函数 }); }); const checkTimeframe = () => { // 先移除所有按钮的chosen类 timeframes.forEach(item => item.element.classList.remove("chosen")); // 给当前选中的按钮添加类 const activeItem = timeframes.find(item => item.name === timeframe); if (activeItem) activeItem.element.classList.add("chosen"); }; // 独立的渲染函数,根据当前timeframe更新页面数据 const renderData = () => { if (!data) return; // 数据未加载时不执行 const timeframeKey = timeframe.toLowerCase(); // 转为小写匹配数据中的key(daily/weekly/monthly) const lastLabelMap = { daily: "Last day", weekly: "Last week", monthly: "Last month" }; for (let i = 0; i < titlesFromDOM.length; i++) { titlesFromDOM[i].textContent = data[i].title; currentFromDOM[i].textContent = `${data[i].timeframes[timeframeKey].current}Hrs`; lastFromDOM[i].textContent = `${lastLabelMap[timeframeKey]} - ${data[i].timeframes[timeframeKey].previous}Hrs`; } }; async function load() { const json = await fetch("/data.json"); data = await json.json(); // 把数据存入全局变量 timeframe = "Daily"; checkTimeframe(); renderData(); // 页面加载时首次渲染 } window.addEventListener("load", load);
改动细节解释
- 批量获取DOM元素:用
getElements函数批量生成元素数组,避免重复写6次getElementById,代码更简洁可维护。 - 全局存储data:页面加载时获取一次数据后,存在全局变量
data中,后续切换无需重新请求。 - renderData函数:核心逻辑,根据当前
timeframe动态获取对应的数据字段,更新页面内容。用timeframe.toLowerCase()匹配数据中的daily/weekly/monthlykey,避免重复的if判断;用lastLabelMap对应不同时间框架的前缀文本,减少冗余。 - 优化checkTimeframe:先移除所有按钮的选中类,再给当前选中的添加,比多个if判断更简洁。
- 按钮点击事件增加renderData调用:每次切换时间框架后,立即调用渲染函数更新页面内容。
这样修改后,页面只会在加载时请求一次数据,点击按钮时直接使用已加载的数据更新页面,完全符合你的需求。
内容的提问来源于stack exchange,提问作者erratinsilentio
相关产品推荐
相关产品推荐

