我正在开发一个具有严格业务需求的应用程序,以显示最多包含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;
});
});
有人对提高此功能性能的方法有什么建议吗?我相信类的添加/删除占用了大部分性能开销,所以我特别希望在那里找到效率。
答案 0 :(得分:2)
表格本身就是开销,特别是当它们包含大量内容时。表也只有在完成时才会呈现。如果可能,请考虑分页。
持续的DOM操作,重新绘制(更改外观)和重排(尺寸变化)也是一种开销。
IE6本身并不是为了进行繁重的JS操作而构建的。 IE6是什么? 10岁?什么是JS 10年前?验证和弹出窗口对吗?
重复的函数调用。在jQuery中,最好缓存函数调用的值,如$(this)
,而不是重复调用它。
正如我在您的代码中所理解的那样,您在鼠标悬停期间运行$.each()
,切片和一些随机数学运算。那很重。
考虑使用更新的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;
});
});
答案 1 :(得分:1)
实际上看起来并不太糟糕。我能想到的唯一一件事就是只计算鼠标悬停时的增量。也就是说,存储前一个开始和结束列/行,并在下一个鼠标悬停事件中,更新仅更改过的元素的类。
其他小事:
$(this)
.find('td.selected')
更改为.find('.selected')
。第一个有两个要检查的条件,而不是一个。在现代浏览器中,第二个肯定更快,因为jQuery可以利用getElementsByClassName
,但在IE6中不存在,那么谁知道呢?
.find('> tr > .selected')