Javascript 加速选择器和方法
在深入研究jQuery/Sizzle源代码之前,我想在这里询问一下如何加快下面的方法 这是一个标准的“全选”复选框方案。标题单元格(Javascript 加速选择器和方法,javascript,jquery,performance,css-selectors,Javascript,Jquery,Performance,Css Selectors,在深入研究jQuery/Sizzle源代码之前,我想在这里询问一下如何加快下面的方法 这是一个标准的“全选”复选框方案。标题单元格()有一个复选框,选中该复选框时,将选中其表的tbody中位于同一列中的所有其他复选框 这项工作: // We want to check/uncheck all columns in a table when the "select all" // header checkbox is changed (even if the table/rows/checkbox
)有一个复选框,选中该复选框时,将选中其表的tbody
中位于同一列中的所有其他复选框
这项工作:
// We want to check/uncheck all columns in a table when the "select all"
// header checkbox is changed (even if the table/rows/checkboxes were
// added after page load).
(function () {
// use this dummy div so we can reattach our table later.
var dummy = $("<div style=display:none />");
// hook it all up!
body.delegate(".js_checkAll", "change", function () {
// cache selectors as much as possible...
var self = $(this),
// use closest() instead of parent() because
// the checkbox may be in a containing element(s)
cell = self.closest("th"),
// Use "cell" here to make the "closest()" call 1 iteration
// shorter. I wonder if "parent().parent()" would be faster
// (and still safe for use if "thead" is omitted)?
table = cell.closest("table"),
isChecked,
index;
// detaching speeds up the checkbox loop below.
// we have to insert the "dummy" div so we know
// where to put the table back after the loop.
table.before(dummy).detach();
index = cell.index();
isChecked = this.checked;
// I'm sure this chain is slow as molasses
table
// get only _this_ table's tbody
.children("tbody")
// get _this_ table's trs
.children()
// get _this_ table's checkboxes in the specified column
.children(":eq(" + index + ") :checkbox")
// finally...
.each(function () {
this.checked = isChecked;
});
// put the table back and detach the dummy for
// later use
dummy.before(table).detach();
});
} ());
//当“全选”时,我们希望选中/取消选中表中的所有列
//标题复选框已更改(即使表格/行/复选框已更改)
//页面加载后添加)。
(功能(){
//使用这个虚拟div,以便稍后可以重新连接表。
虚拟变量=$(“”);
//把它都挂起来!
body.delegate(“.js_checkAll”,“change”,函数(){
//尽可能多地缓存选择器。。。
var self=$(此),
//使用最近的()而不是父级(),因为
//复选框可能位于包含元素中
单元格=自最近(“th”),
//在这里使用“cell”进行“最近的()”调用1次迭代
//更短。我想知道“parent().parent()”是否会更快
//(如果省略了“thead”,则仍可安全使用)?
表=最近的单元格(“表”),
我被检查过,
指数
//分离会加速下面的复选框循环。
//我们必须插入“dummy”div才能知道
//循环结束后,将桌子放回何处。
表.before(dummy).detach();
index=cell.index();
isChecked=此项已检查;
//我敢肯定这条链条很慢
桌子
//只拿这张桌子的主体
.儿童(“tbody”)
//获取此表的trs
.儿童()
//在指定列中获取此表的复选框
.children(“:eq(“+索引+”):复选框”)
//最后。。。
.每个(功能){
this.checked=isChecked;
});
//将桌子放回原位,分离假人,以便
//以后使用
dummy.before(table.detach();
});
} ());
然而,对于250多行,它开始变慢(至少在我的机器上)。用户可能需要最多500行数据,因此分页数据不是解决方案(项目已分页为500/页)
有没有办法再加速一点呢?我不会像那样调用
.children()
。您最好只使用.find()
查找复选框,然后检查父项:
table.find('input:checkbox').each(function(_, cb) {
var $cb = $(cb);
if ($cb.parent().index() === index) cb.checked = isChecked;
});
通过像使用标记名(“输入”)那样调用.find()
,Sizzle将只使用本机getElementsByTagName
(如果不是querySelectorAll
)来获取输入,然后过滤复选框中的输入。我真的怀疑那会更快
如果查找父级索引的成本很高,您可以随时对其进行预计算,并将其存储在父级上的.data()
元素中(或在复选框上)
否。如果省略
,则在HTML中会自动添加
元素,因为在HTML4中,开始标记和结束标记都是“可选”的。因此,在HTML中,它应该是parent().parent().parent()
,但在XHTML中,它作为XML使用,没有可选标记,它应该是parent().parent()
最好还是坚持使用closest()
。更清楚的是,它不是特别慢,而且你只使用了一次,所以它并不重要
index = cell.index();
尽管同样,每个表只有一次索引,所以这并不重要,但是有一个标准的DOM属性可以直接获取表单元格的索引,这比要求jQuery搜索和计数以前的同级要快:index=cell[0]。cellIndex
// we have to insert the "dummy" div so we know
// where to put the table back after the loop.
这有点难看。标准DOM对此有一个更好的答案:记住元素的parentNode
和nextSibling
(如果这是最后一个同级,则可能是null
),完成后可以parent.insertBefore(表,同级)
你应该考虑使用<代码>子()、EQ(index)< /代码>,而不是将其隐藏在选择器中。不会有太大的区别,但更清楚一点
在任何情况下,都可以通过使用更标准的DOM遍历表来节省jQuery的选择器引擎的大量工作:$.each(table[0].tBodies[0].rows, function() {
$(this.cells[index]).find('input[type=checkbox]').each(function() {
this.checked = isChecked;
});
});
选择器查询可以很快,当它们对文档进行操作并且只使用标准CSS选择器时。在这种情况下,jQuery可以将工作传递到浏览器的fastdocument.querySelectorAll
方法。但是范围选择器(find
和$()
的第二个参数)无法优化,因为jQuery和选择器API之间对它们的含义存在分歧,像:eq
和:checkbox
这样的非标准Sizzle选择器将被拒绝。因此:
$('#tableid>tbody>tr>td:nth-child('+(index+1)+') input[type=checkbox]')
在使用
querySelectorAll
的现代浏览器上,速度可能会更快 也许您可以为所有复选框指定一个类,或者您可以尝试停止使用jQuery,因为在某些情况下它可能比自定义代码慢。我将尝试删除一些jQuery选择器。您可以使用JS模板引擎进行大列表操作,它比没有querySelectorAll的DOMEven更快,只需通过getElementsByTagName
快速获取表中的所有输入
元素就可以了,不会吧?会的,但我不知道OP是否希望这样。从获取列索引和避免嵌套表所做的努力来看,我猜可能还有其他输入/复选框/表在其中的某个地方,其内容需要避免。如果没有,那么是的,$(表[0].tBodies[0])。使用getElementsByTagName
查找('input')
)确实是最快的。对-如果确实有很多列复选框,那么最好的做法是在页面生成时用类标记复选框,或者,
$.each(table[0].tBodies[0].rows, function() {
$(this.cells[index]).find('input[type=checkbox]').each(function() {
this.checked = isChecked;
});
});
$('#tableid>tbody>tr>td:nth-child('+(index+1)+') input[type=checkbox]')