Javascript 如何以良好的方式修改大量元素的属性?
我有一个很大的表格,目前由95x120=11400 TD组成,我想动态编辑某一行或某一行中所有单元格的高度和背景色等属性 列,甚至是一组行/列。我想这样做是为了让用户能够调整行/列的大小。 做这件事的好方法是什么Javascript 如何以良好的方式修改大量元素的属性?,javascript,jquery,html,Javascript,Jquery,Html,我有一个很大的表格,目前由95x120=11400 TD组成,我想动态编辑某一行或某一行中所有单元格的高度和背景色等属性 列,甚至是一组行/列。我想这样做是为了让用户能够调整行/列的大小。 做这件事的好方法是什么 顺便说一句,我的表中的所有TD都为row/col添加了唯一的类,例如row1、row2、row3、col1、col2、col3,而该表是通过Javascript构建的。在对如此庞大的结构进行更改时,最好先将其从文档中删除,以便它只在最后得到重新处理,重新插入时 因此,假设您的表位于名为
顺便说一句,我的表中的所有TD都为row/col添加了唯一的类,例如row1、row2、row3、col1、col2、col3,而该表是通过Javascript构建的。在对如此庞大的结构进行更改时,最好先将其从文档中删除,以便它只在最后得到重新处理,重新插入时 因此,假设您的表位于名为table的变量中,您可以执行以下操作:
var prnt = table.parentNode, nxtsbl = table.nextSibling;
prnt.removeChild(table);
// now do all your modifications, such as looping through rows etc.
prnt.insertBefore(table,nxtsbl);
在对如此庞大的结构进行更改时,最好先将其从文档中删除,这样在最后重新插入时,它才会得到重新处理 因此,假设您的表位于名为table的变量中,您可以执行以下操作:
var prnt = table.parentNode, nxtsbl = table.nextSibling;
prnt.removeChild(table);
// now do all your modifications, such as looping through rows etc.
prnt.insertBefore(table,nxtsbl);
如果您的所有单元格都使用适当的类进行标记,那么就非常简单了 假设要更改某列的宽度
$(".col3").width(newWidth);
或者,如果要更改一组列的宽度
$(".col3,.col5").width(newWidth);
同理
$(".row3,.row5,.row9,.row12").height(newHeight);
或者如果你想改变背景颜色
$(".col3").css("background-color","#ff0000");
如果您的所有单元格都使用适当的类进行标记,那么就非常简单了 假设要更改某列的宽度
$(".col3").width(newWidth);
或者,如果要更改一组列的宽度
$(".col3,.col5").width(newWidth);
同理
$(".row3,.row5,.row9,.row12").height(newHeight);
或者如果你想改变背景颜色
$(".col3").css("background-color","#ff0000");
通过动态修改css规则,可以非常有效地实现这一点。存储公共属性(即规则中一行单元格的高度)比将其全部存储在每个元素中更有意义。而且它占用的内存也更少 使用如下所示的表格布局:
<table>
<tr>
<td class="row1 col1">data</td>
<td class="row2 col2">data</td>
<td class="row3 col3">data</td>
</tr>
<tr>
<td class="row1 col1">data</td>
<td class="row2 col2">data</td>
<td class="row3 col3">data</td>
</tr>
<tr>
<td class="row1 col1">data</td>
<td class="row2 col2">data</td>
<td class="row3 col3">data</td>
</tr>
</table>
我们可以这样做:
var numRows=3, numCols=3;
document.getElementsByTagName('head')[0].appendChild(document.createElement('style'));
var sheet=document.styleSheets[1];
//Or instead of creating a new sheet we could just get the first exisiting one like this:
//var sheet=document.styleSheets[0];
var selector, rule, i, rowStyles=[], colStyles=[];
//Create rules dynamically
for (i=0; i<numRows; i++) {
selector=".row"+i;
rule="{height:20px}";
if (sheet.insertRule)
sheet.insertRule(selector+rule, 0);//This puts the rule at index 0
else
sheet.addRule(selector2, rule2, 0);//IE does things differently
rowStyles[i]=(sheet.rules||sheet.cssRules)[0].style;//Remember you have to fetch the rules-array from the sheet and not hold on to the old rules-array, since a new one is created during each insertion. Oh, and IE does things differently again; cssRules instead of rules
}
for (i=0; i<numCols; i++) {
selector=".col"+i;
rule="{background-color:white}";
if (sheet.insertRule)
sheet.insertRule(selector+rule, 0);
else
sheet.addRule(selector2, rule2, 0);
colStyles[i]=(sheet.rules||sheet.cssRules)[0].style;
}
//Now they can be changed real easy and efficiently like this:
//This line changes the height for the second row, simply by modifying their css-rule, not setting a style-height on each element
rowStyles[1].height="50px";
//It is also really easy to adjust properties of rules added from css-file, just iterate through the rules/cssRules-array checking the selectorText-property of each object until the right one is found.
我做了一些基准测试,除非我在某个地方出了问题,否则差异是巨大的。但是,是的,除了基准测试之外,它在实际用例中确实有巨大的显著差异
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title></title>
<style>
td {
border: 1px solid black;
width: 10px;
height: 10px;
}
</style>
<script src="http://code.jquery.com/jquery-latest.min.js " charset="UTF-8"></script>
</head>
<body>
<table id="table">
<tr id="row">
</tr>
</table>
<script type="text/javascript">
var tr=document.getElementById("row");
for (var i=0; i<300; i++) {
var cell=tr.insertCell(0);
cell.className="cell";
}
var sheet=document.styleSheets[0];
var c2=(sheet.rules||sheet.cssRules)[0].style;
var table=document.getElementById("table");
var startTime;
//First loop
startTime=new Date().getTime();
var c1=$(".cell");
for (var i=0; i<1000; i++) {
c1.height(i);
}
var time1=new Date().getTime()-startTime;
//Second loop
startTime=new Date().getTime();
c1=$(".cell");
for (var i=0; i<1000; i++) {
c1.css("height",i);
}
time2=new Date().getTime()-startTime;
//Third loop
startTime=new Date().getTime();
c1=$(".cell");
document.body.removeChild(table);
for (var i=0; i<1000; i++) {
c1.css("height",i);
}
document.body.appendChild(table);
time3=new Date().getTime()-startTime;
//Fourth loop
startTime=new Date().getTime();
for (var i=0; i<1000; i++) {
c2.height=i+"px";
}
var time4=new Date().getTime()-startTime;
alert ("First:"+time1+" ms\nSecond:"+time2+" ms\nThird:"+time3+" ms\nForth:"+time4+" ms");
</script>
</body>
</html>
出于某种原因,这会导致误导吗?在这种情况下,我不太明白我错在哪里,所以我希望得到反馈。
这些是我得到的结果
完成所需时间:
循环1:这个使用一个简单的jquery类选择器$.cell.heighth
铬-2335ms
歌剧院-4151毫秒
IE 9-3965毫秒
Firefox-6252毫秒
Safari-2987 ms
循环2:这一个与上面相同,但使用$.cell.csheight,而不是h。更快
铬-1276ms
歌剧院-3183毫秒
IE 9-2174 ms
Firefox-3685毫秒
Safari-2240毫秒
循环3:与上面相同,但它在修改之前从DOM中删除表,然后重新追加它。至少在Firefox中看起来更快
铬-1259毫秒
歌剧院-3079毫秒
IE 9-2221毫秒
Firefox-2872ms
Safari-2250毫秒
循环4:此循环动态修改css规则:
铬-1毫秒
歌剧院-10毫秒
IE 9-7毫秒
Firefox-2ms
Safari-13毫秒
通过动态修改css规则,可以非常有效地实现这一点。存储公共属性(即规则中一行单元格的高度)比将其全部存储在每个元素中更有意义。而且它占用的内存也更少 使用如下所示的表格布局:
<table>
<tr>
<td class="row1 col1">data</td>
<td class="row2 col2">data</td>
<td class="row3 col3">data</td>
</tr>
<tr>
<td class="row1 col1">data</td>
<td class="row2 col2">data</td>
<td class="row3 col3">data</td>
</tr>
<tr>
<td class="row1 col1">data</td>
<td class="row2 col2">data</td>
<td class="row3 col3">data</td>
</tr>
</table>
我们可以这样做:
var numRows=3, numCols=3;
document.getElementsByTagName('head')[0].appendChild(document.createElement('style'));
var sheet=document.styleSheets[1];
//Or instead of creating a new sheet we could just get the first exisiting one like this:
//var sheet=document.styleSheets[0];
var selector, rule, i, rowStyles=[], colStyles=[];
//Create rules dynamically
for (i=0; i<numRows; i++) {
selector=".row"+i;
rule="{height:20px}";
if (sheet.insertRule)
sheet.insertRule(selector+rule, 0);//This puts the rule at index 0
else
sheet.addRule(selector2, rule2, 0);//IE does things differently
rowStyles[i]=(sheet.rules||sheet.cssRules)[0].style;//Remember you have to fetch the rules-array from the sheet and not hold on to the old rules-array, since a new one is created during each insertion. Oh, and IE does things differently again; cssRules instead of rules
}
for (i=0; i<numCols; i++) {
selector=".col"+i;
rule="{background-color:white}";
if (sheet.insertRule)
sheet.insertRule(selector+rule, 0);
else
sheet.addRule(selector2, rule2, 0);
colStyles[i]=(sheet.rules||sheet.cssRules)[0].style;
}
//Now they can be changed real easy and efficiently like this:
//This line changes the height for the second row, simply by modifying their css-rule, not setting a style-height on each element
rowStyles[1].height="50px";
//It is also really easy to adjust properties of rules added from css-file, just iterate through the rules/cssRules-array checking the selectorText-property of each object until the right one is found.
我做了一些基准测试,除非我在某个地方出了问题,否则差异是巨大的。但是,是的,除了基准测试之外,它在实际用例中确实有巨大的显著差异
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title></title>
<style>
td {
border: 1px solid black;
width: 10px;
height: 10px;
}
</style>
<script src="http://code.jquery.com/jquery-latest.min.js " charset="UTF-8"></script>
</head>
<body>
<table id="table">
<tr id="row">
</tr>
</table>
<script type="text/javascript">
var tr=document.getElementById("row");
for (var i=0; i<300; i++) {
var cell=tr.insertCell(0);
cell.className="cell";
}
var sheet=document.styleSheets[0];
var c2=(sheet.rules||sheet.cssRules)[0].style;
var table=document.getElementById("table");
var startTime;
//First loop
startTime=new Date().getTime();
var c1=$(".cell");
for (var i=0; i<1000; i++) {
c1.height(i);
}
var time1=new Date().getTime()-startTime;
//Second loop
startTime=new Date().getTime();
c1=$(".cell");
for (var i=0; i<1000; i++) {
c1.css("height",i);
}
time2=new Date().getTime()-startTime;
//Third loop
startTime=new Date().getTime();
c1=$(".cell");
document.body.removeChild(table);
for (var i=0; i<1000; i++) {
c1.css("height",i);
}
document.body.appendChild(table);
time3=new Date().getTime()-startTime;
//Fourth loop
startTime=new Date().getTime();
for (var i=0; i<1000; i++) {
c2.height=i+"px";
}
var time4=new Date().getTime()-startTime;
alert ("First:"+time1+" ms\nSecond:"+time2+" ms\nThird:"+time3+" ms\nForth:"+time4+" ms");
</script>
</body>
</html>
出于某种原因,这会导致误导吗?在这种情况下,我不太明白我错在哪里,所以我希望得到反馈。
这些是我得到的结果
完成所需时间:
循环1:这个使用一个简单的jquery类选择器$.cell.heighth
铬-2335ms
歌剧院-4151毫秒
IE 9-3965毫秒
Firefox-6252毫秒
Safari-2987 ms
循环2:这一个与上面相同,但使用$.cell.csheight,而不是h。更快
铬-1276ms
歌剧院-3183毫秒
IE 9-2174 ms
Firefox-3685毫秒
Safari-2240毫秒
循环3:与上面相同,但它在修改之前从DOM中删除表,然后重新追加它。至少在Firefox中看起来更快
铬-1259毫秒
歌剧院-3079毫秒
IE 9-2221毫秒
Firefox-2872ms
Safari-2250毫秒
循环4:此循环动态修改css规则:
铬-1毫秒
歌剧院-10毫秒
IE 9-7毫秒
Firefox-2ms
Safari-13毫秒
您还可以执行table.rows[0],它给出了该行中所有TDs的数组。然后循环遍历它并根据需要进行更改您还可以执行table.rows[0],它给出了该行中所有TDs的数组。然后循环遍历它并根据需要进行更改获取一组要执行操作的元素,迭代该元素列表以更新属性。没有具体的细节,我不确定你能不能有一个具体的答案
。获取要对其执行操作的一组元素,并在该元素列表中迭代更新属性。由于没有具体内容,我不确定你是否能得到具体的答案。使用标签可以更有效地完成专栏。类似地,通过使用标记而不是其中的s,可以更高效地处理行。使用标记可以更高效地处理列。类似地,通过使用标记,而不是使用其中的s,可以更有效地完成行。以编程方式更改CSS规则似乎是一条可行之路。但是,我会修改前三个示例,因为现在在进行此jQuery调用c1=$.cell;之前计时器启动似乎有点不公平;。对所有匹配的单元格进行DOM搜索似乎与精确测量在这些元素上设置CSS属性所需的时间无关。是的,事实上,我是这样写的,但后来改变了它。对于静态大小表,正如您所说,我们可以将$.cell保存到循环外的变量中,但是如果可能添加了新的单元格,我们必须这样做。所以我想这取决于=。我想即使大小是动态的,我们也可以把它放在外面,如果我们确保在大小改变时从c1中添加/删除单元格……好的,我同意大多数时候不需要DOM搜索。比如在调整行大小时。当用户调整大小时,不会添加新单元格。当我能够重新进行基准测试时,我将改变这一点。我打赌差别不会很大,因为jquery在可用时使用document.getElementsByClassName。这方面的工作非常出色。以编程方式更改CSS规则似乎是一条可行之路。但是,我会修改前三个示例,因为现在在进行此jQuery调用c1=$.cell;之前计时器启动似乎有点不公平;。对所有匹配的单元格进行DOM搜索似乎与精确测量在这些元素上设置CSS属性所需的时间无关。是的,事实上,我是这样写的,但后来改变了它。对于静态大小表,正如您所说,我们可以将$.cell保存到循环外的变量中,但是如果可能添加了新的单元格,我们必须这样做。所以我想这取决于=。我想即使大小是动态的,我们也可以把它放在外面,如果我们确保在大小改变时从c1中添加/删除单元格……好的,我同意大多数时候不需要DOM搜索。比如在调整行大小时。当用户调整大小时,不会添加新单元格。当我能够重新进行基准测试时,我将改变这一点。我打赌差别不会很大,因为jquery在可用时使用document.getElementsByClassName。