如何在JavaScript中显式设置HTML表格列宽

时间:2014-09-24 17:16:36

标签: javascript html-table

我在HTML表格中遇到了缩放问题,同时在JavaScript中进行操作。

我有一个JavaScript代码blob,它可以动态地从JSON数组创建一个表。 它修复了标题并允许表体滚动,效果很好。

标题是一个单独的表格,我强烈控制单元格宽度,以确保标题表格的单元格与正文表格单元格匹配。

正文表格单元格的宽度都是明确设置的 我迭代表中的行,然后在该循​​环中对单元格进行交互,并设置每个单元格的宽度。

这个迭代没有扩展,因为行增长到100并且列变为40奇数,我得到Firefox的抱怨,脚本挂起或没有响应。它没有响应,因为它正在忙于设置所有单元格宽度。

nz.dynatable.setTableColumnWidths = function (table, arrayColumnWidths) {
    // Iterate the table and set width settings for each cell
    for (var i = 0; i < table.rows.length; ++i) {
        for (var j = 0; j < table.rows[i].cells.length; ++j) {
            var width = arrayColumnWidths[j] || 0;
            table.rows[i].cells[j].style.width = width.toString() + "px";
        }
    }
}

问:是否可以在一行中为表格设置单元格宽度,并使表格中的所有其他单元格与此一致? Firefox是否因为更改单元格宽度而导致重新计算每个循环的表大小?

完整代码块位于公共GitHub仓库中:https://github.com/Hiblet/DynaTable

2 个答案:

答案 0 :(得分:0)

试试这个:我遇到了同样的问题,这对我很有帮助:

let tables = document.getElementsByClassName("table");

if(tables.length == 2){
    let firstTableCol = tables[0].querySelectorAll('colgroup col');
    let secondTableCol = tables[1].querySelectorAll('tr')[0].querySelectorAll('td');
    if(firstTableCol.length == secondTableCol.length){
        for(let index = 0; index < firstTableCol.length; index++){
            firstTableCol[index].style.width = secondTableCol[index].offsetWidth + "px";
        }
    }else
        console.log('cols count mismatch');
}else
    console.log('count of tables are bigger than 2');

答案 1 :(得分:0)

我尝试了几种方法来修饰这只猫,这是我的发现。最终的解决方案最终变得非常干净和高效,我在Chrome上测试的警告,而不是其他浏览器,以及中等大,但不是很大的表。总结一下,使用css如下来将第5列设置为宽度70,并使用javascript修改该css:

table#my_table th:nth-child(5), table#my_table td:nth-child(5){ max-width:70px; min-width:70px;}

更多详情:

  • 您需要同时设置min-width和max-width,以避免为了保持表格大小不变而不尝试重新调整大小的列来

  • 你可以使用element.style.xxxWidth来做到这一点,但OP中的一个简单方法不能很好地扩展,如OP所说。

    • 解决这个问题的一种方法是仅更新可视区域中的元素(让我们称之为“可视区域方法”)。您可以通过比较父对象和您正在检查的对象的parent.getBoundingClientRect()结果来实现此目的(参见例如How to tell if a DOM element is visible in the current viewport?
    • 只要对getBoundingClientRect()(价格昂贵)的调用保持最小(即每列执行一次,而不是每个单元格),我能够很好地工作。因为在更新可查看的单元格之后,我不想维护更新的内容和不更新的内容的缓存,然后我将使用异步函数调用更新不可查看的单元格。通过这种方式,即使它仍然在后台运行,UI也显得更具响应性
  • 但是,任何涉及对element.style.xxxWidth的直接更改的内容都会感到混乱,尤其是在必须添加代码以仅更新可查看元素之后。此外,尽管这种变化的表现要好得多,但它似乎仍然不是最佳的。所以我最终使用的最终解决方案是执行以下操作(让我们称之为“动态样式表方法”):

    • 假设每个表都有一个唯一的元素ID
    • 通过为每列创建新样式(document.createElement('style'))来初始化表。包含一个规则的样式,该规则仅为具有该ID的表选择该列,例如对于id为“my_table”的表,第5列(cellIndex 4),将宽度设置为70:

      table#my_table th:nth-child(5), table#my_table td:nth-child(5){ max-width:70px; min-width:70px;}
      
    • 将新创建的styleElements添加到table元素(而不是文档)中,这样如果从DOM中删除表,这些额外的样式也会消失

    • 要更改列宽,唯一需要更改的是相关styleElement的规则0的maxWidth / minWidth片段(注意,您也可以使用具有多个规则的单个样式表执行此操作,但我发现它每个列更容易使用单独的样式表,每个列都有一个规则。

总的来说,在我看来,使用动态样式表方法是赢家,原因如下:

  • 它在表格中表现很好,足以在OP中描述的“天真”方法下出现性能问题(尽管我没有比较非常大的表上其他方法的性能)
  • 很干净:不需要进行element.style更改,并且它不会使基本文档DOM混乱,因为相关的样式元素附加到相关表(需要测试跨浏览器)
  • 如果浏览器尚未自动优化其性能,则其设计应通过将性能挑战留给浏览器来进行优化直接进行处理