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

如何高效生成带噪声计算功能的300行HTML表格?

最简实现方案:数据驱动的动态表格生成

核心思路是将所有噪声源数据存入一个数组,通过JavaScript自动生成表格行,彻底避免手动编写300组重复的HTML代码,同时简化后续的数据维护和计算逻辑。

具体实现步骤

1. 定义统一数据源

把所有300组噪声源数据整理成数组,每个元素包含该组的完整参数:

const noiseSources = [
  { name: "101. Ventilationshus (Nordost)", lw: 86, mp1: 19.1, mp2: -11, mp3: -11 },
  { name: "101. Ventilationshus (Sydväst)", lw: 86, mp1: -4.2, mp2: -5, mp3: -5 },
  { name: "102. Ventilationshus (Nordväst)", lw: 89, mp1: 21.5, mp2: -6, mp3: -6 },
  // 在此处继续添加剩余297组数据即可
];

2. 动态生成表格行

页面加载时自动遍历数据源,创建表格行并绑定交互事件,无需手动编写重复HTML:

window.onload = function() {
  const tableBody = document.querySelector('#noiseTable tbody');
  
  // 遍历数据源生成每一行
  noiseSources.forEach((source, index) => {
    const row = document.createElement('tr');
    row.dataset.index = index;
    
    row.innerHTML = `
      <td>${source.name}</td>
      <td>${source.lw}</td>
      <td class="mp1">${source.mp1}</td>
      <td class="mp2">${source.mp2}</td>
      <td class="mp3">${source.mp3}</td>
      <td><input type="number" value="0" class="inputField"></td>
      <td class="sumMP1"></td>
      <td class="sumMP2"></td>
      <td class="sumMP3"></td>
      <td class="recalcMP1" style="display:none;"></td>
      <td class="recalcMP2" style="display:none;"></td>
      <td class="recalcMP3" style="display:none;"></td>
    `;
    
    // 绑定输入事件
    row.querySelector('.inputField').addEventListener('input', () => calculateSum(row));
    tableBody.appendChild(row);
    
    // 初始化行内计算值
    initRowCalculation(row, source);
  });
  
  // 计算初始总噪声水平
  calculateTotal();
};

3. 重构计算逻辑

不再依赖ID定位元素,通过类名和DOM层级获取数据,同时修复原代码的数值格式bug(处理逗号式小数点):

// 初始化单行列计算
function initRowCalculation(row, source) {
  const sumMP1El = row.querySelector('.sumMP1');
  const sumMP2El = row.querySelector('.sumMP2');
  const sumMP3El = row.querySelector('.sumMP3');
  const recalcMP1El = row.querySelector('.recalcMP1');
  const recalcMP2El = row.querySelector('.recalcMP2');
  const recalcMP3El = row.querySelector('.recalcMP3');
  
  sumMP1El.textContent = source.mp1;
  sumMP2El.textContent = source.mp2;
  sumMP3El.textContent = source.mp3;
  
  recalcMP1El.textContent = Math.pow(10, source.mp1 / 10);
  recalcMP2El.textContent = Math.pow(10, source.mp2 / 10);
  recalcMP3El.textContent = Math.pow(10, source.mp3 / 10);
}

// 单行列实时计算
function calculateSum(row) {
  // 处理逗号转小数点,避免parseFloat解析失败
  const mp1 = parseFloat(row.querySelector('.mp1').textContent.replace(',', '.'));
  const mp2 = parseFloat(row.querySelector('.mp2').textContent.replace(',', '.'));
  const mp3 = parseFloat(row.querySelector('.mp3').textContent.replace(',', '.'));
  const input = parseFloat(row.querySelector('.inputField').value) || 0;
  
  // 计算Sum值
  const sumMP1 = mp1 - input;
  const sumMP2 = mp2 - input;
  const sumMP3 = mp3 - input;
  
  // 更新DOM元素
  const sumMP1El = row.querySelector('.sumMP1');
  const sumMP2El = row.querySelector('.sumMP2');
  const sumMP3El = row.querySelector('.sumMP3');
  const recalcMP1El = row.querySelector('.recalcMP1');
  const recalcMP2El = row.querySelector('.recalcMP2');
  const recalcMP3El = row.querySelector('.recalcMP3');
  
  sumMP1El.textContent = sumMP1;
  sumMP2El.textContent = sumMP2;
  sumMP3El.textContent = sumMP3;
  
  recalcMP1El.textContent = Math.pow(10, sumMP1 / 10);
  recalcMP2El.textContent = Math.pow(10, sumMP2 / 10);
  recalcMP3El.textContent = Math.pow(10, sumMP3 / 10);
  
  // 同步更新总噪声水平
  calculateTotal();
}

// 计算总噪声水平
function calculateTotal() {
  let totalMP1 = 0;
  let totalMP2 = 0;
  let totalMP3 = 0;
  
  // 遍历所有行累加计算值
  document.querySelectorAll('#noiseTable tbody tr').forEach(row => {
    totalMP1 += parseFloat(row.querySelector('.recalcMP1').textContent) || 0;
    totalMP2 += parseFloat(row.querySelector('.recalcMP2').textContent) || 0;
    totalMP3 += parseFloat(row.querySelector('.recalcMP3').textContent) || 0;
  });
  
  // 计算对数总和并保留一位小数
  const logTotalMP1 = totalMP1 > 0 ? 10 * Math.log10(totalMP1) : 0;
  const logTotalMP2 = totalMP2 > 0 ? 10 * Math.log10(totalMP2) : 0;
  const logTotalMP3 = totalMP3 > 0 ? 10 * Math.log10(totalMP3) : 0;
  
  document.getElementById('MP1total').textContent = Math.round(logTotalMP1 * 10) / 10;
  document.getElementById('MP2total').textContent = Math.round(logTotalMP2 * 10) / 10;
  document.getElementById('MP3total').textContent = Math.round(logTotalMP3 * 10) / 10;
}

4. 简化HTML结构

只保留表头和总和行,数据行由JS动态生成:

<table id="noiseTable">
  <thead>
    <tr>
      <th>Bullerkälla</th>
      <th>LW</th>
      <th>MP1</th>
      <th>MP2</th>
      <th>MP3</th>
      <th>Input</th>
      <th>Sum MP1</th>
      <th>Sum MP2</th>
      <th>Sum MP3</th>
      <th style="display:none;">Recalculated Sum MP1</th>
      <th style="display:none;">Recalculated Sum MP2</th>
      <th style="display:none;">Recalculated Sum MP3</th>
    </tr>
  </thead>
  <tbody>
    <!-- JS自动生成数据行 -->
  </tbody>
  <tfoot>
    <tr>
      <td colspan="6">Total</td>
      <td id="MP1total"></td>
      <td id="MP2total"></td>
      <td id="MP3total"></td>
      <td colspan="3" style="display:none;"></td>
    </tr>
  </tfoot>
</table>

5. CSS保持原有样式

table {
  width: 100%;
  border-collapse: collapse;
}

th, td {
  border: 1px solid black;
  padding: 15px;
  text-align: left;
}

方案优势

  • 高效扩展:添加300组数据仅需在数组中追加元素,无需手动编写重复HTML。
  • 逻辑清晰:通过类名和DOM关系定位元素,避免大量ID带来的维护混乱。
  • 可维护性高:数据与视图分离,后续修改计算规则或数据结构更便捷。

内容的提问来源于stack exchange,提问作者Mikael Hörnqvist

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 20:35:55