大表中的高性能可选单元 - IE6

时间:2012-05-07 06:47:16

标签: javascript jquery internet-explorer html-table

我正在开发一个具有严格业务需求的应用程序,以显示最多包含60行和最多50列的html表。

理想情况下,用户可以选择单个表格单元格,也可以单击并拖动以选择多个单元格。

我的问题是我目前仅限于使用IE6,而且我一直在寻找(或编码)一种方法,以便在这么多单元上进行这种选择而不会严重降低性能。

我当前的方法看起来基本上是这样的:

$(document).ready(function() {
    var selecting = false;
    var colStart, rowStart;

    var tableContainer = $("#tableContainer")

    tableContainer.delegate("td", "mousedown", function() {
        //Clear Selection
        tableContainer.find("td.selected").removeClass("selected");

        $(this).addClass("selected");
        colStart = $(this).index();
        rowStart = $(this).parents("tr").index();
        selecting = true;
    }).delegate("td", "mouseover", function() {
        if (selecting) {
            //Clear Selection
            tableContainer.find("td.selected").removeClass("selected");

            var theCell = $(this);

            // Get the row and column numbers of the current cell 
            var colEnd = theCell.index();
            var rowEnd = theCell.parents("tr").index();

            // Account for rowEnd being smaller than rowStart
            var rowSliceStart = Math.min(rowStart, rowEnd);
            var rowSliceEnd = Math.max(rowStart, rowEnd);

            tableContainer.find("tr").slice(rowSliceStart, rowSliceEnd + 1).each(function() {
                var colSliceStart = Math.min(colStart, colEnd);
                var colSliceEnd = Math.max(colStart, colEnd);

                // Add the required class to the children
                $(this).children().slice(colSliceStart, colSliceEnd + 1).addClass("selected");
            });
        }
    }).delegate("td", "mouseup", function() {
        selecting = false;
    });
});​

有人对提高此功能性能的方法有什么建议吗?我相信类的添加/删除占用了大部分性能开销,所以我特别希望在那里找到效率。

2 个答案:

答案 0 :(得分:2)

  1. 表格本身就是开销,特别是当它们包含大量内容时。表也​​只有在完成时才会呈现。如果可能,请考虑分页。

  2. 持续的DOM操作,重新绘制(更改外观)和重排(尺寸变化)也是一种开销。

  3. IE6本身并不是为了进行繁重的JS操作而构建的。 IE6是什么? 10岁?什么是JS 10年前?验证和弹出窗口对吗?

  4. 重复的函数调用。在jQuery中,最好缓存函数调用的值,如$(this),而不是重复调用它。

  5. 正如我在您的代码中所理解的那样,您在鼠标悬停期间运行$.each(),切片和一些随机数学运算。那很重。

  6. 考虑使用更新的jQuery

  7. 另外,我已经清理了一些代码:

    $(function() {
        var selecting = false,
            tableContainer = $("#tableContainer"),
            colStart, rowStart;
    
        tableContainer.on("mousedown", 'td', function() {
            var $this = $(this); //reference this
            colStart = $this.index();
            rowStart = $this.closest("tr").index(); //use closest instead of parents to avoid going up to root
            $(".selected", tableContainer).removeClass("selected"); //context instead of find
            $this.addClass("selected");
    
            selecting = true;
        }).on("mouseover", 'td', function() {
            if (selecting) {
    
                var theCell = $(this),
                    colEnd = theCell.index(),
                    rowEnd = theCell.closest("tr").index(), //use closest
                    rowSliceStart = Math.min(rowStart, rowEnd),
                    rowSliceEnd = Math.max(rowStart, rowEnd);
    
                $(".selected", tableContainer).removeClass("selected");
    
                $("tr", tableContainer).slice(rowSliceStart, rowSliceEnd + 1).each(function() {
                    var colSliceStart = Math.min(colStart, colEnd),
                        colSliceEnd = Math.max(colStart, colEnd);
                    $('> *', this).slice(colSliceStart, colSliceEnd + 1).addClass("selected"); //using selector to get children instead of $(this).children()
                });
            }
        }).on("mouseup", 'td', function() {
            selecting = false;
        });
    });​
    

答案 1 :(得分:1)

实际上看起来并不太糟糕。我能想到的唯一一件事就是只计算鼠标悬停时的增量。也就是说,存储前一个开始和结束列/行,并在下一个鼠标悬停事件中,更新仅更改过的元素的类。

其他小事:

  • 在mousedown处理程序中缓存$(this)
  • 对于IE6,我不是100%肯定这个,但您可以尝试将选择器从.find('td.selected')更改为.find('.selected')。第一个有两个要检查的条件,而不是一个。在现代浏览器中,第二个肯定更快,因为jQuery可以利用getElementsByClassName,但在IE6中不存在,那么谁知道呢?
    • 您还可以尝试制作更具针对性的选择器,尤其是当单元格的内容包含更多DOM元素时。 .find('> tr > .selected')
  • 限制鼠标悬停处理程序。