本文介绍了如何以良好的方式修改大量元素的属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个大表,当前由95x120 = 11400 TD组成,并且希望动态地编辑属性,例如来自特定行或
列的所有单元格的高度和背景颜色,甚至是一堆行/列。我想这样做是为了让用户能够调整行/列的大小。
完成这件事的好方法是什么?

我的表中的所有TD都按顺序具有唯一的行/列类,例如row1,row2,row3,col1,col2,col3动态添加通过Javascript构建。

解决方案

这可以通过动态修改css规则来实现。这也使得在规则中存储公共属性,即一行单元格的高度更有意义,而不是将其全部存储在每个单元中。而且它占用的内存也少。



使用如下的表格布局:

 <表> 
< tr>
< td class =row1 col1>资料< / td>
< td class =row2 col2> data< / td>
< td class =row3 col3> data< / td>
< / tr>
< tr>
< td class =row1 col1>资料< / td>
< td class =row2 col2> data< / td>
< td class =row3 col3> data< / td>
< / tr>
< tr>
< td class =row1 col1>资料< / 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];
//或者不是创建一个新工作表,我们可以像这样获得第一个现存工作表:
// var sheet = document.styleSheets [0];
var选择器,规则,我,rowStyles = [],colStyles = [];
//动态创建规则
(i = 0; i selector =。row+ i;
rule ={height:20px};
if(sheet.insertRule)
sheet.insertRule(selector + rule,0); //这将规则放在索引0
else
sheet.addRule(selector2,rule2 ,0); // IE做不同的事情
rowStyles [i] =(sheet.rules || sheet.cssRules)[0] .style; //记住你必须从表单中获取规则数组,不保留旧规则数组,因为在每次插入期间都会创建一个新数组。噢,IE再次做不同的事情; (i = 0; i< numCols; i ++){
selector =。col+ i; cssRules)而不是规则
}
;
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;
}

//现在可以像这样简单高效地改变它们:
//这行改变了第二行的高度,只需修改它们的css-rule ,不在每个元素上设置样式高度
rowStyles [1] .height =50px;
//调整从css-file添加的规则的属性也非常简单,只需遍历规则/ cssRules数组,检查每个对象的selectorText属性,直到找到正确的对象。

我做了一些基准测试,除非我在某个地方出错,差别非常大。但是,除了基准测试之外,它确实在真实用例中有着巨大的显着差异。

 <!DOCTYPE html> 
< html lang =en>
< head>
< meta charset =utf-8/>
< title>< / title>

< style>
td {
border:1px纯黑;
width:10px;
height:10px;
}
< / style>
< script src =http://code.jquery.com/jquery-latest.min.jscharset =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 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;


//第一个循环
startTime = new Date()。getTime();
var c1 = $(。cell);
for(var i = 0; i c1.height(i);
}
var time1 = new Date()。getTime() - startTime;
//第二个循环
startTime = new Date()。getTime();
c1 = $(。cell);
for(var i = 0; i c1.css(height,i);
}
time2 = new Date()。getTime() - startTime;
//第三个循环
startTime = new Date()。getTime();
c1 = $(。cell);
document.body.removeChild(table);
for(var i = 0; i c1.css(height,i);
}
document.body.appendChild(table);
time3 = new Date()。getTime() - startTime;
//第四个循环
startTime = new Date()。getTime();
for(var i = 0; i c2.height = i +px;
}
var time4 = new Date()。getTime() - startTime;

alert(First:+ time1 +ms\\\
Second:+ time2 +ms\\\
Third:+ time3 +ms\\\
Forth:+ time4 +ms);
< / script>
< / body>
< / html>

由于某些原因,这样的结果会产生误导吗?在这种情况下,我不能完全明白我要出错的地方,所以我会很感激反馈。
这些是我得到的结果。



完成时间:

循环1:这个使用了一个简单的jquery类选择器$(。cell)。height(h);


  • Chrome - 2335 ms

  • Opera - 4151 ms
  • IE 9 - 3965 ms

  • Firefox - 6252 ms循环2:这一个与上面的相同,但是使用$($)。
  • Safari - 2987 ms



(.cell).css(height,h)代替。速度更快




  • Chrome - 1276 ms

  • Opera - 3183 ms

  • IE 9 - 2174 ms

  • Firefox - 3685 ms
  • Safari - 2240 ms


循环3:与上面相同,但它在修改之前从DOM中删除表,然后重新添加它。在Firefox中似乎更快至少




  • Chrome - 1259 ms

  • Opera - 3079 ms

  • IE 9 - 2221 ms

  • Firefox - 2872 ms

  • Safari - 2250 ms



循环4:这一个动态修改css规则: b
$ b


  • Chrome - 1毫秒

  • Opera - 10毫秒

  • IE 9 - 7毫秒

  • Safari - 13毫秒


I have a large table currently consisting of 95x120=11400 TD's and would like to dynamically edit properties such as height and background-color for all the cells from a certain row or column, or even a bunch of rows/columns. I want to do this in order to make the user able to resize rows/columns among other things.What would be a good way of getting that done?

All the TD's in my table does by the way have unique class for row/col eg row1, row2, row3, col1, col2, col3 added dynamically while the table is built up though Javascript.

解决方案

This can be done really efficiently by modifying css-rules dynamically. It also makes a lot more sense storing common properties i.e. height for a row of cells in a rule rather than storing it all in each element. And it takes up less memory as well.

With a table-layout like the following:

<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>

We can do something like this:

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.

I did a bit of benchmarking and unless I'm going wrong somewhere the difference is quite tremendous. But yeah, apart from the benchmark it really does a huge noticeable difference in the real use case.

<!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>

Would results from this be misleading for some reason? In that case I can't quite see where I'm going wrong so I'd appreciate feedback.These are the results I get.

Time taken to complete:

Loop 1: This one uses a simple jquery class-selector $(".cell").height(h);

  • Chrome - 2335 ms
  • Opera - 4151 ms
  • IE 9 - 3965 ms
  • Firefox - 6252 ms
  • Safari - 2987 ms

Loop 2: This one is same as above but uses $(".cell").css("height",h) instead. It's faster

  • Chrome - 1276 ms
  • Opera - 3183 ms
  • IE 9 - 2174 ms
  • Firefox - 3685 ms
  • Safari - 2240 ms

Loop 3: Same as above but it removes the table from DOM before modifying, then re-appending it. Seems faster in Firefox at least

  • Chrome - 1259 ms
  • Opera - 3079 ms
  • IE 9 - 2221 ms
  • Firefox - 2872 ms
  • Safari - 2250 ms

Loop 4: This one modifies the css-rules dynamically:

  • Chrome - 1 ms
  • Opera - 10 ms
  • IE 9 - 7 ms
  • Firefox - 2 ms
  • Safari - 13 ms

这篇关于如何以良好的方式修改大量元素的属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-30 14:11