发布在:性能

优化选择器

选择器优化不再像以前那么重要,因为越来越多的浏览器实现了 document.querySelectorAll(),选择器的负担从 jQuery 转移到了浏览器。但是,当选择器性能成为瓶颈时,仍有一些提示需要记住。

链接 jQuery 扩展

如果可能,避免使用包含 jQuery 扩展 的选择器。这些扩展无法利用原生 querySelectorAll() DOM 方法提供的性能提升,因此需要使用 jQuery 提供的 Sizzle 选择器引擎。

1
2
3
4
5
// Slower (the zero-based :even selector is a jQuery extension)
$( "#my-table tr:even" );
// Better, though not exactly equivalent
$( "#my-table tr:nth-child(odd)" );

请记住,许多 jQuery 扩展(包括上述示例中的 :even)在 CSS 规范中没有确切的对应项。在某些情况下,这些扩展的便利性可能会超过其性能成本。

链接 尝试隔离选择中的非标准部分

当您选择元素时,jQuery 会使用您的选择调用 querySelectorAll。如果 querySelectorAll 抛出错误,jQuery 会引用其 Sizzle 引擎。因此,如果您使用至少一个非标准伪类,如 :contains():has:even:submit 等,则无法利用原生 querySelectorAll

1
2
3
4
5
// A long selection with nonstandard pseudo-classes inside
$( "#global.ready .part .list li a:contains('qwerty'):first" );
// A long standard selection with a filter outside (faster)
$( "#global.ready .part .list li a").filter( ":contains('qwerty'):first" );

链接 避免过度指定

1
2
3
4
$( ".data table.attendees td.gonzalez" );
// Better: Drop the middle if possible.
$( ".data td.gonzalez" );

“扁平化”DOM 也有助于提高选择器性能,因为选择器引擎在查找元素时要遍历的层数更少。

链接 保存对 querySelectorAll 的调用

querySelectorAll 已经非常快了,如果你想保持这种速度,请尝试尽可能少地调用它。

1
2
3
4
5
6
// If in your HTML there are 2 .container with 5 div in each,
// this line will call querySelectorAll 13 times (1 + 2 + 2*5).
$( ".container" ).children( "div" ).find( ".robotarm" );
// Against only 1 call with this:
$( ".container div .robotarm" );

链接 适用于较旧浏览器的提示

当需要支持较旧浏览器(例如 Internet Explorer 8 及更低版本)时,请考虑以下提示

链接 特异性

在选择器的右侧要具体,在左侧要不太具体。

1
2
3
4
5
// Unoptimized:
$( "div.data .gonzalez" );
// Optimized:
$( ".data td.gonzalez" );

如果可能,在最右侧的选择器上使用 tag.class,在左侧仅使用标签或仅使用 .class

链接 避免使用通用选择器

指定或暗示可以在任何地方找到匹配项的选择可能会非常慢。

1
2
3
$( ":radio" ); // Implied universal selection.
$( "*:radio" ); // Same thing, explicit now.
$( "input:radio" ); // Much better.