:nth-of-type() 在 jQuery / Sizzle 中?

Posted

技术标签:

【中文标题】:nth-of-type() 在 jQuery / Sizzle 中?【英文标题】::nth-of-type() in jQuery / Sizzle? 【发布时间】:2011-01-06 19:01:58 【问题描述】:

令我惊讶的是Sizzle(jQuery 使用的选择器引擎)带有内置的:nth-child() 选择器,但缺少:nth-of-type() 选择器。

为了说明:nth-child():nth-of-type() 之间的区别并说明问题,请考虑the following html document:

<!doctype html>
<html>
 <head>
  <meta charset="utf-8">
  <title>:nth-of-type() in Sizzle/jQuery?</title>
  <style>
   body p:nth-of-type(2n)  background: red; 
  </style>
 </head>
 <body>
  <p>The following CSS is applied to this document:</p>
  <pre>body p:nth-of-type(2n)  background: red; </pre>
  <p>This is paragraph #1.</p>
  <p>This is paragraph #2. (Should be matched.)</p>
  <p>This is paragraph #3.</p>
  <p>This is paragraph #4. (Should be matched.)</p>
  <div>This is not a paragraph, but a <code>div</code>.</div>
  <p>This is paragraph #5.</p>
  <p>This is paragraph #6. (Should be matched.)</p>
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
  <script>
   $(function() 
    // The following should give every second paragraph (those that had red backgrounds already after the CSS was applied) an orange background.
    // $('body p:nth-of-type(2n)').css('background', 'orange');
   );
  </script>
 </body>
</html>

由于 Sizzle 使用浏览器原生的 querySelector()querySelectorAll() 方法,如果它们存在(即在已经实现 Selectors API 的浏览器中),像 $('body p:nth-child'); 这样的东西当然可以工作。但它在旧版浏览器中无法使用,因为 Sizzle 没有此选择器的备用方法。

是否可以轻松地将 :nth-of-type() 选择器添加到 Sizzle,或者在 jQuery 中实现它(也许通过使用 the built-in :nth-child() selector)? custom selector with parameters 会很好。

【问题讨论】:

不确定,但$('p:even') 不会为您提供所需的内容吗?你已经有了选择器 (p),所以你只需要过滤它。 @Kobi:没那么容易。选择器p:nth-child(2n) 将匹配每个父元素中 中的每隔一个段落。如果有两个 DIV,都包含三个段落,则以下段落(按 DOM 顺序)将与 p:nth-child(2n) 匹配:#2、#5。看?这不仅仅是获取文档中的每个P,然后将其过滤到每个 mnth 元素的问题。是的,$('p:even')$('p:nth-child(2n)') 的别名,但不是 $('p:nth-of-type(2n)') 的别名。另外,我在这个例子中使用了2n,当然其他变体也应该是可能的。 知道了,并删除了我的答案。 Nick Craver,就像我在我的帖子中解释的那样,这是因为 Firefox 是具有选择器 API 的本机实现的浏览器之一。 Sizzle 不知道 :nth-of-type() 选择器,但 Firefox 的 querySelectorAll() 知道。这就是它“有效”的原因——但这并不是因为 Sizzle。最好在 Sizzle 中使用它,因为它可以在 所有 浏览器中使用。 你不知道吗,它没有实现仅仅是因为John Resig didn't think it was worth implementing。 【参考方案1】:
/**
 * Return true to include current element
 * Return false to exclude current element
 */
$.expr[':']['nth-of-type'] = function(elem, i, match) 
    if (match[3].indexOf("n") === -1) return i + 1 == match[3];
    var parts = match[3].split("+");
    return (i + 1 - (parts[1] || 0)) % parseInt(parts[0], 10) === 0;
;

Test case -(签入 IE 或重命名选择器

你当然也可以添加偶数&奇数

match[3] = match[3] == "even" ? "2n" : match[3] == "odd" ? "2n+1" : match[3];

【讨论】:

酷!这就是我一直在寻找的;一个简短、聪明、简洁的解决方案。如您所知,:odd:even 已经在 jQuery 中得到支持,只是不在 :nth-of-type(odd) / :nth-of-type(even) 形式中,但为了完整性,也可以将它们放在其中。 更新:更多选择器,见github.com/keithclark/JQuery-Extended-Selectors 很好,但我只是想警告其他人这个解决方案总是假设一个周期性(n)。我的意思是,像 :nth-of-type(2n):nth-of-type(2) 这样的过滤器将是相同的(当后者应该只是第二个元素,而不是所有偶数元素时)。【参考方案2】:

jQuery 插件 moreSelectors 支持 nth-of-type(以及许多其他选择器)。我建议要么使用它,要么简单地实现一个简单的插件,只实现你需要的确切选择器。您应该能够从那里复制粘贴代码。

黑客愉快!

【讨论】:

【参考方案3】:

我不能假装知道 nth-of-type 是如何实现的,但是 jQuery 确实提供了一种机制,您可以通过它创建自己的自定义选择器。

以下问题涉及自定义选择器,可能会为您提供有用的见解

What useful custom jQuery selectors have you written?

【讨论】:

是的,我知道这一点……我可能应该将其添加到我的帖子中。

以上是关于:nth-of-type() 在 jQuery / Sizzle 中?的主要内容,如果未能解决你的问题,请参考以下文章

[ jquery 选择器 :nth-of-type() ] 选取指定类型(p)父元素下的第几个子元素

nth-of-type在选择class的时候需要注意的一个小问题

在 selenium 中选择 Nth-of-type

查漏补缺——说说:nth-of-type(3n)选择器

IE8:用啥代替 nth-of-type(n)?

CSS3中:nth-child和:nth-of-type的区别深入理解