代码之家  ›  专栏  ›  技术社区  ›  David Murdoch

加速选择器和方法

  •  2
  • David Murdoch  · 技术社区  · 15 年前

    在深入研究jQuery/Sizzle源代码之前,我想在这里问一下如何加快下面的方法。

    <thead><tr><th> )有一个复选框,选中该复选框时将选中其表中的所有其他复选框 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();
    
        });
    } ());
    

    有什么办法再加快一点吗?

    2 回复  |  直到 15 年前
        1
  •  1
  •   bobince    15 年前
    // I wonder if "parent().parent()" would be faster 
    // (and still safe for use if "thead" is omitted)?
    

    不,如果 <thead> 在HTML中省略 <tbody> 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.
    

    parentNode nextSibling null 如果这是最后一个兄弟姐妹)等你做完了你就可以 parent.insertBefore(table, sibling) .

            .children("tbody")
            .children()
            .children(":eq(" + index + ") :checkbox")
            .each(function () {
                this.checked = isChecked;
            });
    

    .children().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可以将工作传递给浏览器的fast document.querySelectorAll 方法。但作用域选择器( find $() )无法优化,因为jQuery和选择器API在它们的含义上存在分歧,而非标准的Sizzle选择器 :eq :checkbox 会被拒绝的。所以这个:

    $('#tableid>tbody>tr>td:nth-child('+(index+1)+') input[type=checkbox]')
    

    querySelectorAll !

        2
  •  2
  •   Pointy    15 年前

    .children() 像那样。你最好还是用 .find() 要找到复选框,然后选中父项:

    table.find('input:checkbox').each(function(_, cb) {
      var $cb = $(cb);
      if ($cb.parent().index() === index) cb.checked = isChecked;
    });
    

    只是打个电话 .find() 与标记名('input')类似,Sizzle将只使用本机 getElementsByTagName querySelectorAll )要获取输入,请筛选这些复选框。我真的怀疑这样会更快。

    如果查找父索引变得昂贵,则可以预先计算该索引并将其存储在 .data() 父元素上的元素(或复选框上的右键)。