我有一个循环通过类'GridCell'的表格cel中的所有div。 在某些情况下,当调整网格或列的大小时,需要这样做。
我扩展了行数和列数,以查看更多的时差,现在循环大约为750毫秒。
但我不明白的是,“只是循环的一部分”要快得多。请参阅以下三个循环。第一个是缓慢的。仅执行第一个循环的一部分的第二个和第三个循环非常快。
//Around 750 ms
$('table.Grid tbody td.GridCell > div').each(function() {
var width = $(this).parent().width();
$(this).css('width', width - 3);
});
//Around 60 ms
$('table.Grid tbody td.GridCell > div').each(function() {
var width = $(this).parent().width();
});
//Around 15 ms
$('table.Grid tbody td.GridCell > div').each(function() {
$(this).css('width', 100);
});
所以一行,只有60或15毫秒,但两者一起是750.这有什么区别?
P.S。我执行循环的顺序无关紧要。第一个循环总是比其他循环慢得多,也就是最后执行该循环时。
答案 0 :(得分:2)
在第一个循环中,您正在计算计算的宽度,然后将其应用于每次迭代的另一个元素。在第二个循环中,您所做的只是计算宽度,并将其分配给变量。在第三个循环中,您只是应用静态内联样式。
我所说的是最后两个循环组合起来并不等于第一个循环的功能,所以第一个循环比其他两个循环慢,这并不奇怪。
你应该尝试类似的东西:
var $divs = $('table.Grid tbody td.GridCell > div'),
m = [];
// case 1
$divs.each(function() {
var width = $(this).parent().width();
$(this).css('width', width - 3);
});
// case 2
$divs.each(function() {
m.push( $(this).parent().width() );
}).each(function(i) {
$(this).css('width', m[i] - 3);
});
我在这里做了一个简单的性能测试:http://jsperf.com/tablewidth,差异似乎非常小。
答案 1 :(得分:2)
// collect the widths from the first row only
var widths = $('table.Grid tbody tr:first-child td.GridCell').map(function(idx) {
return $(this).width() - 3;
// or use:
// return this.clientWidth - 3;
// if you're not targeting IE <= 7
});
// apply the widths to each div
$('table.Grid tbody td.GridCell > div').each(function(idx) {
this.style.width = widths[idx % widths.length] + 'px';
});
答案 2 :(得分:1)
var $rows = $('table.Grid tbody').children('tr');
// we only need the widths from the first row
var widths = $rows.first().children('td').map(function() {
return $(this).width() - 3;
}).get();
// process each row individually
$rows.each(function() {
$('td.gridCell > div', this).css('width', function(i) {
return widths[i];
});
});
答案 3 :(得分:0)
在你的第一个例子中
$('table.Grid tbody td.GridCell > div').each(function() {
var width = $(this).parent().width();
$(this).css('width', width - 3);
});
您正在评估$(this)
两次。试着写一下
$('table.Grid tbody td.GridCell > div').each(function() {
var $this = $(this);
var width = $this.parent().width();
$this.css('width', width - 3);
});
或甚至更好(编辑:不确定)也尝试使用each()
方法传递的当前元素
$('table.Grid tbody td.GridCell > div').each(function(i, el) {
var $this = $(el);
var width = $this.parent().width();
$this.css('width', width - 3);
});
答案 4 :(得分:0)
如果你使用
怎么办?$('table.Grid tbody td.GridCell > div').each(function(i,domEle) {
$(domEle).css('width', $(domEle).parent().width() - 3);
});
并尝试在jQuery中使用优化选择器
答案 5 :(得分:0)
假设父宽度的计算不是动态的(子剂量的大小调整会影响父级),宽度是恒定的(大的,如果是)。
var width = $(this).parent().width();
$('table.Grid tbody td.GridCell > div').each(function() {
$(this).css('width', width - 3);
});
答案 6 :(得分:0)
我很难说出确切的细节,但我理解这个问题:
var width = $(this).parent().width();
- 你打电话给这个,浏览器被迫让你获得所选元素的真实尺寸。
$(this).css('width', 100);
- 这会导致浏览器重排文档。所以你运行这一行,浏览器必须重新计算页面的一部分。
为什么第一个比其他两个循环慢?我看到它就像你只做var width = $(this).parent().width();
时它可以计算所有宽度一次并从缓存中给出它们。
现在当你只做这行$(this).css('width', 100);
时 - 浏览器可以等待直到执行脚本。并立即重绘所有更新元素。
但是,当您执行第一个循环时,强制浏览器计算宽度,而不是更新某个元素。维度缓存已损坏。现在你又想要获得宽度,浏览器必须重绘页面。因此,每当它只能执行一次时,它会将对页重绘为其他两个循环。
答案 7 :(得分:0)
这不一定是JS问题! 忘记循环,你根本不需要使用JS / jQuery来实现所需的功能。 / p>
要使.GridCell
的子div占用所有可用宽度减去3px ,您可以使用以下CSS规则:
.GridCell>div {
width:auto; /*take up all available width (for block elements)*/
margin:0 1.5px; /*add a 1.5px buffer on both sides of the div*/
}
如果你想要真的很花哨并且不关心浏览器兼容性矩阵有点差,你可以依赖CSS3 calc()
:
.GridCell>div {
width:calc(100% - 3px); /*look up vendor-specific prefixes of the property
if you want for this to work on more browsers*/
margin: 0 auto; /*now that the width is calculated correctly above,
center the div. Or don't!*/
}
答案 8 :(得分:0)
好的,这是另一种选择:
$('table.Grid tbody td.GridCell > div').css('width', function() {
return $(this.parentNode).width() - 3;
});