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

High performance selectable cells in large table - IE6

本文关键字:选单 单元格 IE6 高性能      更新时间:2023-09-26

我正在开发一个具有严格业务需求的应用程序,以显示最多 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;
    });
});​

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

  1. 表本身就是开销,尤其是当它们包含大量内容时。表也仅在完成时呈现。如果可能,请考虑分页。

  2. 不断的 DOM 操作、重绘(改变外观)和重排(改变尺寸)也是一个开销。

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

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

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

  6. 考虑使用较新的 jQuery

另外,我已经清理了一些您的代码:

$(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;
    });
});​

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

其他小事:

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