38

我有以下结构

<ul id="tabs" class="nav nav-tabs">
    <li><a href="#aaa" hashval="aaa">AAA</a></li>
    <li><a href="#bbb" hashval="bbb">BBB</a></li>
    <li><a href="#ccc" hashval="ccc">CCC</a></li>
    <li><a href="#ddd" hashval="ddd">DDD</a></li>
</ul>

现在我正在通过以下代码对锚标记进行操作,并且工作正常。

$('#tabs a[href="#ddd"]').tab('show');

我正在使用 pycharm,它通过说“带有 ID 选择器的前言”为该行添加警告。当我单击它时,pycharm 更改为以下

$('#tabs').find('a[href="#ddd"]').tab('show');

两者都工作正常,但我不明白其中的区别。

$('#tabs a[href="#ddd"]')两者有什么区别,或者更具体地说,和之间有什么区别$('#tabs').find('a[href="#ddd"]')

4

7 回答 7

52

$("#tabs a")从右到左 求值- 这是Sizzle选择器引擎的本机方向querySelectorAll- 即首先它找到页面中的所有锚元素,然后将其缩小到#tabs.

$("#tabs").find("a")评估 - 更直观地 -从左到右,即首先它找到#tabs,然后找到它下面的锚元素。

显然后者会产生更好的性能,但它只会累积起来才明显;也就是说,如果您运行数千个查询。否则,差异可以忽略不计。

于 2013-07-10T11:48:40.087 回答
7

“从左到右增加特异性”中所述:

对 jQuery 的选择器引擎有一点了解是很有用的。它首先从最后一个选择器开始工作,因此在旧浏览器中,查询如下:

$("p#intro em");

将每个 em 元素加载到数组中。然后它处理每个节点的父节点并拒绝那些找不到 p#intro 的节点。如果页面上有数百个 em 标签,查询效率会特别低。

根据您的文档,可以通过首先检索最合格的选择器来优化查询。然后它可以用作子选择器的起点,例如

$("em", $("p#intro")); // or
$("p#intro").find("em");

但是测试用例$("#tabs > a")最快

于 2013-07-10T11:51:42.147 回答
5

第二个要快得多。原因是 jQuery 的选择器 enginge Sizzle ,它从右遍历选择,反之亦然。

这意味着选择器

$('#tabs a[href="#ddd"]')

首先在 DOM 文档中查询一个标签,该标签包含设置为的属性 。然后它会过滤掉所有这些,以获得每一个标签。最后,它遍历每个节点的 DOM 树,试图找到一个父节点。href#ddd<a>#tabs

想象一个带有 1000 个标签的网站,href="#ddd"这将是多么的慢。

然后。

pycharm 建议的另一个变体是首先定位一个元素#tabs。这是超级快的,因为 jQuery 可以利用本机浏览器方法getElementById()。有了这个节点,它可以向下遍历找到所有匹配的标签。通过这样做,不需要all tags in the whole DOM-tree检查。只有那些实际上在#tabs.

有关详细信息,请查看文档中的此页面

于 2013-07-10T11:50:12.727 回答
2

效果是一样的:查找值为#dddashref并且是 的后代的锚点#tabs。不同之处在于实现这一目标的方式。

第一个解决方案找到锚点,然后检查它们是否是#tabs.

第二个解决方案找到#tabs然后找到锚点。当然,这应该更快。

于 2013-07-10T11:50:20.507 回答
2

.find()与您的第一个选择器相比,性能更好

$('#tabs a[href="#ddd"]').tab('show');

,这就是为什么 pycharm 使用.find()

$('#tabs').find('a[href="#ddd"]').tab('show');

http://vaughnroyko.com/the-real-scoop-on-jquery-find-performance/

于 2013-07-10T11:51:06.613 回答
2

不同之处在于 find() 允许您根据已经做出的选择过滤一组元素,如果是这种情况,则返回元素数组。

$('#tabs').find('a[href=“#ddd”]');

这是一种更具体的搜索元素的方式,因为你说的是​​“嘿,去那里#tabs找到我a[href=“#ddd”]”而不是说“嘿,在$('#tabs a[href=“#ddd”]')我拥有的所有代码中找到我所有这些人”。

于 2013-07-10T11:54:01.297 回答
1

虽然在大多数情况下,性能是唯一的差异,但方法的差异也会影响代码的结果,具体取决于您使用的选择器。

例如,$("table").find("tr:even").addClass("even");将“偶数”类添加到返回的每个单独表中的每隔一行。因此,如果“偶数”类使行中的文本变为粗体,并且您有两个表,每个表有 3 行,您将得到以下结果:


这是表一,第 1 行

这是表一,第 2 行

这是表一,第 3 行


这是表二,第 1 行

这是表二,第 2 行

这是表二,第 3 行


在这两种情况下,每个表的第 1 行和第 3 行(即“偶数”行......不要让我开始使用 JQuery 的even过滤器,选择奇数行......)是粗体的。

另一方面,$("table tr:even").addClass("even");将“偶数”类添加到所有表组合的整个行组中的每隔一行。


这是表一,第 1 行

这是表一,第 2 行

这是表一,第 3 行


这是表二,第 1 行

这是表二,第 2 行

这是表二,第 3 行


在这种情况下,第二个表的第 1 和第 3 行实际上是整个<tr>元素组的第 4 和第 6 行,因此它们被视为“奇数”。但是,第二个表的第 2 行是整个集合的第 5 行,因此被视为“偶数”并以粗体显示。

于 2013-07-10T15:56:29.363 回答