【问题标题】:How to set HTML Table column widths explicitly in JavaScript如何在 JavaScript 中显式设置 HTML 表格的列宽
【发布时间】:2014-11-19 07:03:31
【问题描述】:

我在使用 JavaScript 操作 HTML 表格时遇到了缩放问题。

我有一个 JavaScript 代码块,可以从 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

【问题讨论】:

  • 你试过只做第一行吗?这是正常的表行为。
  • 是的,这是老派的把戏,只需在第一行设置宽度 - 并祈祷不涉及 colspans :P 有人再使用 colgroup 了吗?
  • 没有 colspans,这一切都在我的控制之下。将试一试第一排,如果可行,它将大大加快该部分的速度。明天试试,谢谢回复。
  • 抱歉耽搁了。第一排就够了,太好了。 @isherwood 会提供一个象征性的答案,以便我可以将其标记为这样吗?非常感谢你们俩的帮助。
  • 注意:当我对行进行排序并重新排序时,最上面的行不再是表格中的第一个,格式被填满了;我必须存储列宽并在排序后重置第一行。 GitHub 已更新。一切都好!

标签: javascript html-table


【解决方案1】:

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

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');

【讨论】:

  • 我通过缓存当前列宽并将它们滚动到重建的表来解决这个问题。我想我会重写我的内部表格更新代码来更新数据,而不是表格和数据,因为构建 HTML 似乎是个问题。
【解决方案2】:

我尝试了几种方法给这只猫剥皮,以下是我的发现。最终的解决方案非常干净和高效,我在 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 添加到表格元素(而不是文档),这样如果表格从 DOM 中移除,这些额外的样式也会消失

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

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

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

【讨论】:

  • 一个更实质性的示例代码块将使这个答案更有帮助
猜你喜欢
  • 1970-01-01
  • 2012-08-13
  • 2020-09-15
  • 2014-05-24
  • 2016-06-28
  • 2011-09-18
  • 2015-10-02
  • 1970-01-01
  • 2010-10-30
相关资源
最近更新 更多