1

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

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

4

2 回答 2

2
  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;
    });
});​
于 2012-05-07T07:10:43.817 回答
1

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

其他小事:

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