菜鸟科技网

如何利用js动态获得数据形成菜单表格

现代Web开发中,使用JavaScript(JS)动态获取数据并生成菜单表格是一项非常实用的技能,它允许网页内容根据后端提供的数据实时更新,无需重新加载整个页面,以下是详细的步骤和示例代码,帮助你掌握这一技术。

如何利用js动态获得数据形成菜单表格-图1
(图片来源网络,侵删)

前期准备与基础概念

要实现这个功能,首先需要明确几个关键点:数据的来源(通常是API接口)、DOM操作(创建/修改页面元素)、以及事件处理(如点击交互),最常见的场景是从服务器通过HTTP请求获取JSON格式的数据,然后解析这些数据来构建表格结构,假设我们的后端提供了一个返回如下格式数据的接口:

{
  "items": [
    {"id": 1, "name": "首页", "url": "/home", "parentId": null},
    {"id": 2, "name": "产品中心", "url": "/products", "parentId": null},
    {"id": 3, "name": "子分类A", "url": "/suba", "parentId": 1},
    {"id": 4, "name": "子分类B", "url": "/subb", "parentId": 2}
  ]
}

这里的每个对象代表一个菜单项,包含ID、名称、链接地址和父级ID(用于构建层级关系)。


核心实现步骤详解

发送异步请求获取数据

使用fetchXMLHttpRequest发起网络请求,推荐使用现代浏览器广泛支持的fetch API,其语法更简洁且基于Promise。

// 定义获取数据的函数
async function loadMenuData() {
  try {
    const response = await fetch('https://example.com/api/menu'); // 替换为真实接口地址
    if (!response.ok) throw new Error('网络错误');
    const result = await response.json(); // 解析JSON响应体
    return result.items; // 提取需要的数组部分
  } catch (error) {
    console.error('获取数据失败:', error);
    return []; // 出错时返回空数组避免崩溃
  }
}

注意:实际项目中需考虑跨域问题(CORS),可通过设置响应头Access-Control-Allow-Origin解决;生产环境还应添加加载状态提示(如旋转图标)。

如何利用js动态获得数据形成菜单表格-图2
(图片来源网络,侵删)

设计数据结构与映射逻辑

收到原始数据后,可能需要对其进行预处理以适应展示需求,比如上述例子中的嵌套关系,可以通过建立一个以parentId为键的对象来进行分组:

function organizeByParent(flatList) {
  const map = {}; // 临时存储容器
  flatList.forEach(item => {
    if (!map[item.parentId]) map[item.parentId] = []; // 如果该父节点不存在则初始化空数组
    map[item.parentId].push(item); // 将当前项添加到对应父节点下
  });
  return map; // 返回按父ID组织好的树形结构
}

此时得到的结果是类似这样的对象:{null: [...], 1: [...], 2: [...]},其中键为父ID,值为子节点列表,这种形式便于后续递归渲染多级菜单。

动态创建DOM元素生成表格

接下来是最关键的一步——根据整理后的数据逐层创建HTML元素,这里采用递归函数处理任意深度的嵌套:

// 主入口函数:启动整个流程
function initMenuTable() {
  loadMenuData().then(data => {
    const organizedData = organizeByParent(data);
    const container = document.getElementById('menuContainer'); // 确保HTML中有这个占位符<div id="menuContainer"></div>
    container.innerHTML = ''; // 清空原有内容以防重复添加
    renderTableRows(organizedData, container); // 开始渲染第一层(parentId=null)
  });
}
// 递归渲染每一行的通用方法
function renderTableRows(nodes, parentElement, level = 0) {
  nodes.forEach(node => {
    // 创建tr元素并设置缩进样式体现层级感
    const tr = document.createElement('tr');
    tr.style.paddingLeft = `${level  20}px`; // 根据层级增加左边距
    // 填充单元格内容
    const tdName = document.createElement('td');
    tdName.textContent = node.name;
    tr.appendChild(tdName);
    const tdLink = document.createElement('td');
    const aTag = document.createElement('a');
    aTag.href = node.url;
    aTag.target = '_blank'; // 新标签页打开链接
    aTag.textContent = '查看详情';
    tdLink.appendChild(aTag);
    tr.appendChild(tdLink);
    parentElement.appendChild(tr); // 将完整行插入父容器
    // 如果存在子节点,继续向下递归渲染
    if (node.children && node.children.length > 0) {
      const subTable = document.createElement('table');
      subTable.border = '1'; // 可选边框线增强可读性
      renderTableRows(node.children, subTable, level + 1); // 传递更新后的层级参数
      tr.appendChild(subTable); // 把子表挂载到当前行的末尾
    }
  });
}

优化技巧:对于大量数据的情况,可以考虑虚拟滚动技术减少性能开销;或者使用文档片段(DocumentFragment)批量插入节点以提高渲染效率。

如何利用js动态获得数据形成菜单表格-图3
(图片来源网络,侵删)

绑定交互行为增强用户体验

为了让生成的菜单更具实用性,可以为某些元素添加额外的功能,例如给每一行的标题添加鼠标悬停效果:

// 修改之前的renderTableRows函数中的相关部分
tdName.addEventListener('mouseover', () => {
  tr.style.backgroundColor = '#f0f0f0'; // 浅灰色背景突出显示
});
tdName.addEventListener('mouseout', () => {
  tr.style.backgroundColor = ''; // 恢复默认颜色
});

还可以实现展开/折叠功能,特别是当菜单项较多时:

// 在renderTableRows内部判断是否有子节点的情况下添加按钮控件
if (node.children && node.children.length > 0) {
  const expandBtn = document.createElement('button');
  expandBtn.textContent = '+'; // 默认显示加号表示可展开
  expandBtn.onclick = function() {
    this.textContent = this.textContent === '+' ? '-' : '+'; // 切换符号
    subTable.style.display = this.textContent === '-' ? 'table' : 'none'; // 控制子表显隐
  };
  tr.insertBefore(expandBtn, tr.firstChild); // 放在最前面的位置
}

这样用户就能自由控制复杂菜单的展示细节了。


完整示例整合

以下是将所有片段组合在一起的完整代码模板:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">动态菜单表格演示</title>
  <style>
    table { width: 100%; border-collapse: collapse; margin-bottom: 20px; }
    th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
    th { background-color: #eee; font-weight: bold; }
    tr:hover { background-color: #fafafa; } / 整行悬停高亮 /
  </style>
</head>
<body onload="initMenuTable()">
  <h2>网站导航菜单</h2>
  <div id="menuContainer"></div>
  <script>
    // ...上面提到的所有JavaScript代码放在这里...
  </script>
</body>
</html>

只需将上述脚本嵌入到合适的位置即可运行,你可以用本地服务器测试(比如VS Code的Live Server插件),或者部署到线上环境验证效果。


常见问题排查指南

现象 可能原因 解决方案
页面空白无内容 API路径错误/跨域限制 检查URL是否正确;确认服务器允许跨域访问
数据显示不全 JSON解析失败 确保响应头的Content-Type设置为application/json
层级不生效 parentId未正确关联 调试organizeByParent函数的逻辑是否正确分组
CSS样式混乱 优先级冲突 使用开发者工具检查具体元素的最终应用样式

FAQs(常见问题解答)

Q1: 如果后端返回的不是标准JSON怎么办?
A: 你可以使用第三方库如papaparse解析CSV文件,或者手动编写转换逻辑处理其他格式(如XML),关键在于确保最终能得到统一的结构化数据对象供前端使用,记得在请求头中声明接受的内容类型(例如Accept: application/csv)。

Q2: 如何保证动态生成的表格在不同设备上正常显示?
A: 采用响应式设计理念,利用CSS媒体查询调整布局,例如针对小屏幕设备隐藏部分次要信息,改用垂直堆叠方式排列单元格,同时避免固定宽度单位(如px),优先使用百分比或rem等相对单位,还可以借助Bootstrap

分享:
扫描分享到社交APP
上一篇
下一篇