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

JavaScript HTML表格排序异常:新表格点击后页面无响应

表格排序函数导致页面无响应问题排查与修复

问题现象

  • 已有JavaScript排序函数可正常对第一个HTML表格(tableBeingDecomm)进行排序
  • 对第二个表格(PortsTable)执行排序时,无报错但页面直接无响应

相关代码

正常工作的表格代码

<table id="tableBeingDecomm" align="center" render-area="beingDecom">
    <thead>
        <tr>
            <th id="beingDecom"><a href="#">
                Server Name
                <img src='/icons/sort.png' width='20' height='20' style='display:inline;'>
            </a></th>
            <th id="beingDecomDate"><a href="#">
                Deleting Date
                <img src='/icons/sort.png' width='20' height='20' style='display:inline;'>
            </a></th>
        </tr>
    </thead>
    <tbody render-action="loop">
        <tr render-data="jsonBeingDecomm">
            <td>{!serverName!}</td>
            <td>{!deletingDate!}</td>
        </tr>
    </tbody>
</table>

导致问题的表格代码

<table id="PortsTable" align="center" render-area="dcPorts">
    <thead>
        <tr>
            <th id="ServerNameHeader1"><a href="#">
                Server Name
                <img src='/icons/sort.png' width='20' height='20' style='display:inline;'>
            </a></th>
            <th id="ServerNameHeader2"><a href="#">
                Destination
                <img src='/icons/sort.png' width='20' height='20' style='display:inline;'>
            </a></th>
            <th>Port 53</th>
            <th>Port 88</th>
            <th>Port 135</th>
            <th>Port 139</th>
            <th>Port 389</th>
            <th>Port 445</th>
            <th>Port 464</th>
            <th>Port 636</th>
        </tr>
    </thead>
    <tbody render-action="loop">
        <tr render-data="jsonPorts">
            <td>{!Server Name!}</td>
            <td>{!Destination!}</td>
            <td>{!Port 53!}</td>
            <td>{!Port 88!}</td>
            <td>{!Port 135!}</td>
            <td>{!Port 139!}</td>
            <td>{!Port 389!}</td>
            <td>{!Port 445!}</td>
            <td>{!Port 464!}</td>
            <td>{!Port 636!}</td>
        </tr>
    </tbody>
</table>

原排序函数代码

function sortTable(tableId, column) {
    var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;
    table = document.getElementById(tableId);
    switching = true;
    dir = "asc";
    while (switching) {
      switching = false;
      rows = table.rows;
      for (i = 1; i < (rows.length - 1); i++) {
        shouldSwitch = false;
        x = rows[i].getElementsByTagName("td")[column];
        y = rows[i + 1].getElementsByTagName("td")[column];
        if (!isNaN(x.innerHTML) && !isNaN(y.innerHTML)) {
          if (dir == "asc") {
            if (Number(x.innerHTML) > Number(y.innerHTML)) {
              shouldSwitch= true;
              break;
            }
          } else if (dir == "desc") {
            if (Number(x.innerHTML) < Number(y.innerHTML)) {
              shouldSwitch= true;
              break;
            }
          }
        } else {
          if (dir == "asc") {
            if (x.innerHTML.toLowerCase() > y.innerHTML.toLowerCase()) {
              shouldSwitch= true;
              break;
            }
          } else if (dir == "desc") {
            if (x.innerHTML.toLowerCase() < y.innerHTML.toLowerCase()) {
              shouldSwitch= true;
              break;
            }
          }
        }
      }
      if (shouldSwitch) {
        rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
        switching = true;
        switchcount ++;
      } else {
        if (switchcount == 0 && dir == "asc") {
          dir = "desc";
          switching = true;
        }
      }
    }
  }

let sortOrder = "asc";

调用代码

document.getElementById("ServerNameHeader1").addEventListener("click", function() {
sortTable("PortsTable", 0);
});
document.getElementById("ServerNameHeader2").addEventListener("click", function() {
sortTable("PortsTable", 1);
});

问题原因分析

  1. 无限循环触发:函数每次执行都会重置dir = "asc",忽略外部sortOrder变量。当表格存在大量重复内容时,升序排序完成后switchcount为0,会触发切换为降序并重新循环;但降序排序同样因重复内容导致switchcount为0,又切换回升序,陷入无限循环,直接导致页面无响应。
  2. 行范围处理错误:table.rows包含thead和tbody的所有行,循环从i=1开始但用rows.length -1做判断,会遗漏最后一行的比较。
  3. 排序逻辑不严谨:使用innerHTML可能受HTML标签干扰,数字判断仅用isNaN存在误判情况。

修复方案

修改后的排序函数

// 为每个表格独立维护排序状态,避免跨表格冲突
const tableSortStates = {};

function sortTable(tableId, column) {
    var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;
    table = document.getElementById(tableId);
    
    // 初始化当前表格的排序方向,默认升序
    if (!tableSortStates[tableId]) {
        tableSortStates[tableId] = "asc";
    }
    dir = tableSortStates[tableId];
    switching = true;

    while (switching) {
        switching = false;
        // 仅获取tbody中的数据行,避免处理thead行
        rows = table.tBodies[0].rows;
        
        // 循环覆盖所有相邻数据行的比较
        for (i = 0; i < (rows.length - 1); i++) {
            shouldSwitch = false;
            x = rows[i].getElementsByTagName("td")[column];
            y = rows[i + 1].getElementsByTagName("td")[column];
            
            // 处理文本内容,去除前后空格,避免干扰排序
            const xValue = x.textContent.trim();
            const yValue = y.textContent.trim();
            
            // 准确判断是否为数字类型
            const isXNumber = !isNaN(xValue) && !isNaN(parseFloat(xValue));
            const isYNumber = !isNaN(yValue) && !isNaN(parseFloat(yValue));

            if (isXNumber && isYNumber) {
                const xNum = parseFloat(xValue);
                const yNum = parseFloat(yValue);
                // 根据当前排序方向判断是否需要交换
                shouldSwitch = dir === "asc" ? xNum > yNum : xNum < yNum;
            } else {
                const xStr = xValue.toLowerCase();
                const yStr = yValue.toLowerCase();
                shouldSwitch = dir === "asc" ? xStr > yStr : xStr < yStr;
            }
            
            if (shouldSwitch) break;
        }

        if (shouldSwitch) {
            rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
            switching = true;
            switchcount++;
        } else {
            // 更新当前表格的排序方向
            tableSortStates[tableId] = dir === "asc" ? "desc" : "asc";
            // 无交换发生时直接跳出循环,避免无限循环
            break;
        }
    }
}

关键改进点

  • 新增tableSortStates对象,为每个表格独立维护排序方向,避免全局变量冲突
  • 直接获取tbody中的数据行,简化循环起始索引,避免处理thead行
  • 使用textContent.trim()替代innerHTML,排除HTML标签和空格对排序的干扰
  • 优化数字判断逻辑,使用parseFloat确保准确识别数字类型
  • 修改循环结束逻辑:无交换发生时直接切换排序方向并跳出循环,彻底避免无限循环

内容的提问来源于stack exchange,提问作者sigfried

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 10:55:51