You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Vanilla JS变量状态切换展示数据的实现问题

解决时间追踪仪表盘的时间框架切换问题(仅加载一次数据)

你当前代码的核心问题是:数据渲染逻辑只在页面加载时执行了一次,点击daily/weekly/monthly按钮时,仅更新了timeframe变量和按钮样式,但没有触发新的数据渲染。要实现仅加载一次数据并切换展示,需要把渲染逻辑抽离成可复用的函数,在每次切换时调用。

关键改动点

  1. 将获取到的data存储为全局变量,确保页面加载后数据可被后续渲染逻辑访问
  2. 提取renderData独立函数,接收当前timeframe作为参数,负责更新页面数据
  3. 在按钮点击事件中,更新timeframe后调用renderData函数
  4. 优化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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 14:55:20