jQuery/JavaScript如何更快地计算宽度

3

我有一个拥有100列的表格。我正在遍历所有th元素,明确设置每个th的宽度。

var $ths = $("table th");
$ths.each(function (i, th) {
    var $th = $(th);
    var width = $th.width();
    $th.width(width);
});

对于100列,这需要太多的时间(超过60秒)。 每个“获取宽度”的调用需要500-700毫秒。 这是因为每次我获取宽度时都需要生成布局。

问题 - 有没有更快的方法来获取宽度?

原因 - 我正在冻结标题。 为此,我需要将每个标题的宽度设置为固定像素宽度。 一切都是动态的,预设每列的宽度不是一个选项。


2
为什么你不能用CSS来做这个? - Blender
你能解释一下“冻结表头”是什么意思吗?这是否意味着给定列中的任何内容都不能超过其表头的宽度? - lbstr
我已经对你的代码进行了负载测试,使用 jQuery 运行速度已经达到了极限。 - Cory Danielson
尝试使用本机JavaScript:elem.offsetWidth = elem.offsetWidth;哦,@ajax81已经提到了。 - Johannes Egger
在CSS中使用"$th.css("width")"或者在纯JavaScript中使用并不能帮助我太多,因为它们都会重新排版。我尝试了detach,但结果是所有的宽度都等于0,所以这不是一个选项。我将尝试使用visibility:hidden,但我担心它可能与detach相同。我会继续更新进展。 - Tejas
显示剩余3条评论
2个回答

3
你可以考虑使用普通的 JavaScript 来编写这个。 可能会节省一些毫秒的时间。
var cells = myTable.rows[0].children;

for ( var i = 0; i < cells.length; i++ ){
   cells[i].style.width = cells[i].offsetWidth + "px";
}

因为您正在使用offsetWidth,您无法避免回流。然而,通过根据TH中的字符数估算单元格宽度(假设文本不换行且使用固定的等宽字体)并创造性地应用CSS可以大大减少回流延迟
// Appends CSS Classes to stylesheet in doc head
function appendStyle(styles) {
  var css = document.createElement('style');
  css.type = 'text/css';

  // Browser compatibility check
  if (css.styleSheet) css.styleSheet.cssText = styles;
  else css.appendChild(document.createTextNode(styles));

  document.getElementsByTagName("head")[0].appendChild(css);
}

var cells       = myTable.rows[0].children;
var cellWidth   = 0;
var letterWidth = 5; // let's assume each letter is 5px wide
var classname   = '';
var styles      = '';

for ( var i = 0; i < cells.length; i++ ){
   classname         = "Cell" + i;
   cell[i].className = classname;
   cellWidth         = (letterWidth * cells[i].innerHTML.length);
   styles           += "." + classname + "{width:" + cellWidth + "px}";
} 

window.onload = function() { appendStyle(styles) };

你甚至可以使用文档片段 (John Resig的性能优化文章) 进一步进行优化,通过在运行时在 DOM 外部呈现整个内容,并在加载完 DOM 后替换片段...但是,说真的,在这一点上,你必须认真考虑果汁是否值得榨取。

感谢您抽出时间回答。使用本地js并没有太大帮助。我的表格是在页面加载后动态创建的,所以我必须在此之后调用appendStyles。假设每个字母的宽度来计算宽度的想法有一定的潜力,我会尝试一下。对于企业应用程序的业务用户来说,冻结标题非常重要。我们正在使用同一页动态创建数百个不同的视图(网格)。所有的努力绝对是值得的。 - Tejas
@Tejas:没问题。我非常好奇你是如何解决这个问题的。当你解决了它,能否将你的解决方案作为编辑发布在你的问题中? - Daniel Szabo

0

你可以为每个列单独添加一个 onload 回调函数,在其中设置列的宽度。这样,不再需要使用循环,而是在加载时逐个处理。这只是一个想法,但可能有效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接