jQuery替代支持类的nth-child选择器

时间:2016-10-22 01:00:54

标签: javascript jquery html css css-selectors

我有这样的结构:

<div class="parent">
    <div class="randomclass">...</div>
    <div class="item">Item 1</div>
    <div class="item">Item 2</div>
    <div class="item">Item 3</div>
    <div class="randomclassdifferentname">...</div>
    <div class="item">Item 4</div>
    <div class="item">Item 5</div>
    <div class="item">Item 6</div>
    <div class="item">Item 7</div>
    ...
</div>
<div class="parent">
    <div class="anotherclass">...</div>
    <div class="item">Another item 1</div>
    <div class="item">Another item 2</div>
    <div>...</div>
    <div class="item">Another item 3</div>
    ...
</div>

我只需要选择 .parent div 的第n个 .item div 类子项(计数器会为每个父节点重置)。

例如,我想选择每个第三个“div.item”元素,因此我希望影响内容为“第3项”的元素,“第6项“,”另一项目3 “。

规则:

  • 所需的类总是应用于“div”元素(可能并不重要)。
  • 父母总是“父”类,也总是“div”元素。
  • 在div中,可以有其他具有随机类名称(或没有)的div(或任何其他类型的元素),这些不得干扰第n个计数器。
  • 元素也可以嵌套,因此每个项类元素都可以包含另一个父类元素,并且还包含另一个项类元素。

不幸 CSS选择器

div.parent div.item:nth-child(3n)

nth-child()无法正常工作。尽管效果仅应用于具有给定类的元素,但计数本身并不正确,因为它还会计算没有给定类的元素。

我怀疑是否会有纯CSS解决方案,而且因为我实际上将它用作jQuery选择器,我想要一些简单的jQuery替代方案。谢谢你们给我任何帮助。

5 个答案:

答案 0 :(得分:5)

您可以根据他们在父级中拥有的索引来过滤相关于具有相同类别的其他项目的项目

$('.item').filter(function(_,item) {
    return ($(item).siblings('.item').addBack().index(item)+1) % 3 === 0;
}).css('color','red');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="parent">
    <div class="randomclass">...</div>
    <div class="item">Item 1</div>
    <div class="item">Item 2</div>
    <div class="item">Item 3</div>
    <div class="randomclassdifferentname">...</div>
    <div class="item">Item 4</div>
    <div class="item">Item 5</div>
    <div class="item">Item 6</div>
    <div class="item">Item 7</div>
    ...
</div>
<div class="parent">
    <div class="anotherclass">...</div>
    <div class="item">Another item 1</div>
    <div class="item">Another item 2</div>
    <div>...</div>
    <div class="item">Another item 3</div>
    ...
</div>

答案 1 :(得分:1)

如果你想要某个jQuery集合的nth元素,你需要在该集合上使用.eq()选择器。如... ...

&#13;
&#13;
var allItems = $('.parent').find('.item');
for (i = 1; i <= allItems.length/3; i++) {
  allItems.eq((i*3)-1).css({'border':'1px solid red'})
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent">
    <div class="randomclass">...</div>
    <div class="item">Item 1</div>
    <div class="item">Item 2</div>
    <div class="item">Item 3</div>
    <div class="randomclassdifferentname">...</div>
    <div class="item">Item 4</div>
    <div class="item">Item 5</div>
    <div class="item">Item 6</div>
    <div class="item">Item 7</div>
    ...
</div>
<div class="parent">
    <div class="anotherclass">...</div>
    <div class="item">Another item 1</div>
    <div class="item">Another item 2</div>
    <div>...</div>
    <div class="item">Another item 3</div>
    ...
</div>
&#13;
&#13;
&#13;

以上内容将在整个收集过程中保持统计(无论父母如何)。如果您希望每位家长单独处理,请在.each()上使用$('.parent')。如... ...

&#13;
&#13;
$('.parent').each( function(){
    var theseItems = $(this).find('.item');
    for (i = 1; i <= theseItems.length/3; i++) {
        theseItems.eq((i*3)-1).css({border:'1px solid red'})
    }
})
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div class="parent">
        <div class="randomclass">...</div>
        <div class="item">Item 1</div>
        <div class="item">Item 2</div>
        <div class="item">Item 3</div>
        <div class="randomclassdifferentname">...</div>
        <div class="item">Item 4</div>
        <div class="item">Item 5</div>
        <div class="item">Item 6</div>
        <div class="item">Item 7</div>
        ...
    </div>
    <div class="parent">
        <div class="anotherclass">...</div>
        <div class="item">Another item 1</div>
        <div class="item">Another item 2</div>
        <div>...</div>
        <div class="item">Another item 3</div>
        ...
    </div>
&#13;
&#13;
&#13;

答案 2 :(得分:1)

  

我怀疑会有纯CSS解决方案

对于纯css解决方案,您可以使用General siblings combinator选择器~

  

两个序列所代表的元素共享同一个父元素   文档树和第一个序列表示的元素   先于(不一定是立即)由...表示的元素   第二个。

使用两个选择器。在第一个选择器,匹配所需的元素。在第一个选择器后面的第二个选择器匹配元素处,为在第一个匹配元素处设置的属性设置默认值或使用unset

/* match third `div.item` */
.parent div.item ~ div.item ~ div.item {
  color: sienna;
  font-size: 2em;
}
/* match fourth through last `div.item` */
.parent div.item ~ div.item ~ div.item ~ div.item {
  color: unset;
  font-size: unset;
}
<div class="parent">
  <div class="randomclass">...</div>
  <div class="item">Item 1</div>
  <div class="item">Item 2</div>
  <div class="item">Item 3</div>
  <div class="randomclassdifferentname">...</div>
  <div class="item">Item 4</div>
  <div class="item">Item 5</div>
  <div class="item">Item 6</div>
  <div class="item">Item 7</div>
  ...
</div>
<div class="parent">
  <div class="anotherclass">...</div>
  <div class="item">Another item 1</div>
  <div class="item">Another item 2</div>
  <div>...</div>
  <div class="item">Another item 3</div>
  <div class="item">Another item 4</div>
  <div class="item">Another item 5</div>
  ...
</div>

  

我只需要选择.parent div的第n个.item div class子   (计数器重置每个父节点)。

     

例如,我想选择每个第三个“div.item”元素,所以我就是这样   期望影响内容“第3项”,“第6项”的元素,   “另一项3”

最初没有注意到要求是选择每个第三个元素。

您仍然可以在css函数中使用General sibling combinator .querySelector()选择器和javascript返回单个元素,以返回预期结果。

该函数当前接受父元素作为选择器字符串或DOM元素,后代元素选择器,引用后代选择器选择之间距离的数字,调用每个匹配元素的回调,返回数组中的匹配元素。

for循环中的

for..of循环最多迭代childSelector.length / nth次。使用nth循环中的for数字参数构造选择器字符串; .querySelector()返回单个元素,然后递增nth参数,该参数从先前匹配的元素创建选择器匹配nth元素以进行下一次迭代;消除了for循环必须迭代childSelector.length的所有parentSelector元素以匹配所需选择器的必要性。

const gen = function* (arg) {
    yield* arg[Symbol.iterator] ? arg : [arg] 
};
window.onload = function() {
  // `parentSelector`: `".parent"`, `document.querySelector(".parent")`,
  // `document.querySelectorAll(".parent"),
  // `document.getElementsByClassName(".parent")`
  // `childSelector`: `".item"`; `nth`: `3`; `callback`: function
  function nthElement(parentSelector, childSelector, nth, callback) {
    let [nthparents, selector, n, items] = [
          typeof parentSelector === "string"
            ? document.querySelectorAll(parentSelector)
            : [...gen(parentSelector)]
          , childSelector
          , nth
          , []
        ];
    for (let nthp of nthparents) {
      for (let i = n; i <= nthp.querySelectorAll(selector).length; i += n) {
        let item = nthp.querySelector(Array(i).fill(selector).join("~"));
        items.push(item);
        callback.call(item, i, item, nthp)
      }
    };
    return items
  }
  // select every `nth` third `.item` element  
  // that is a child of `.parent` element
  let items = nthElement(document.querySelectorAll(".parent"), ".item", 3
              , function (i, nth, nthParent) {
                  console.log(i, nth, nthParent);
                  this.style.color = "sienna";
                  this.style.fontSize = "2em";
              });
  console.log(items);
}
<div class="parent">
  <div class="randomclass">...</div>
  <div class="item">Item 1</div>
  <div class="item">Item 2</div>
  <div class="item">Item 3</div>
  <div class="randomclassdifferentname">...</div>
  <div class="item">Item 4</div>
  <div class="item">Item 5</div>
  <div class="item">Item 6</div>
  <div class="item">Item 7</div>
  ...
  <div class="randomclass">...</div>
  <div class="randomclass">...</div>
  <div class="randomclass">...</div>
  <div class="item">Item 8</div>
</div>

<div class="parent">
  <div class="anotherclass">...</div>
  <div class="item">Another item 1</div>
  <div class="item">Another item 2</div>
  <div>...</div>
  <div class="item">Another item 3</div>
  <div class="anotherclass">...</div>
  <div class="item">Another item 4</div>
  <div class="item">Another item 5</div>
  ...
  <div class="anotherclass">...</div>
  <div class="anotherclass">...</div>
  <div class="anotherclass">...</div>
  <div class="item">Another item 6</div>
</div>

使用jQuery

$(function() {
  function nthElement(childSelector, nth, callback) {
    let [nthparents, selector, n, items] = [
        Array.from(this)
        , childSelector
        , nth
        , []
        ];
    for (let nthp of nthparents) {
      for (let i = n; i <= nthp.querySelectorAll(selector).length; i += n) {
        let item = nthp.querySelector(Array(i).fill(selector).join("~"));
        items.push(item);
        callback.call(item, i, item, nthp)
      }
    };
    return jQuery(items)
  }
  // set `nthElement` as a jQuery method
  $.fn.extend({nthElement: nthElement});

  // select every third `.item` element  that is a child of `.parent` element
  var items = $(".parent").nthElement(".item", 3, function(i, nth, nthParent) {
    console.log(i, nth, nthParent);
    $(this).css({color: "sienna",fontSize: "2em"});   
  });      
  console.log(items);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<div class="parent">
  <div class="randomclass">...</div>
  <div class="item">Item 1</div>
  <div class="item">Item 2</div>
  <div class="item">Item 3</div>
  <div class="randomclassdifferentname">...</div>
  <div class="item">Item 4</div>
  <div class="item">Item 5</div>
  <div class="item">Item 6</div>
  <div class="item">Item 7</div>
  ...
  <div class="randomclass">...</div>
  <div class="randomclass">...</div>
  <div class="randomclass">...</div>
  <div class="item">Item 8</div>
</div>

<div class="parent">
  <div class="anotherclass">...</div>
  <div class="item">Another item 1</div>
  <div class="item">Another item 2</div>
  <div>...</div>
  <div class="item">Another item 3</div>
  <div class="anotherclass">...</div>
  <div class="item">Another item 4</div>
  <div class="item">Another item 5</div>
  ...
  <div class="anotherclass">...</div>
  <div class="anotherclass">...</div>
  <div class="anotherclass">...</div>
  <div class="item">Another item 6</div>
</div>

答案 3 :(得分:-1)

nth-child选择器不是类敏感的。它按名称而不是按类选择元素。见jquery nth-child

  

:nth-​​child(n)伪类很容易与:eq(n)混淆,即使这两者可能导致显着不同的匹配元素。使用:nth-​​child(n),所有子节点都被计数,无论它们是什么,只有在与附加到伪类的选择器匹配时才选择指定的元素。使用:eq(n)只计算附加到伪类的选择器,不限于任何其他元素的子元素,并且选择第(n + 1)个(n为0)。

虽然eq(n)是类敏感的,但它不支持方程作为参数。

所以我认为没有直接的方法来使用css来实现它。

尝试使用一些js代码。

答案 4 :(得分:-1)

纯CSS选择器不可能实现这一点。但是,如果您可以灵活地使用唯一标记名称而不是div.item,则可以实现这一点。如果您可以将div.item元素更改为p标记,则可以执行以下操作。

&#13;
&#13;
.parent p:nth-of-type(3n) {
  color: red;
}
.parent {
  padding: 10px;
  border: 1px solid black;
}
.item {
  border: 1px dotted black;
}
&#13;
<div class="parent">
  <div class="randomclass">Random</div>
  <p class="item">Item 1</p>
  <p class="item">Item 2</p>
  <p class="item">Item 3</p>
  <div class="randomclassdifferentname">Random different Name</div>
  <p class="item">Item 4</p>
  <p class="item">Item 5</p>
  <p class="item">Item 6</p>
  <p class="item">Item 7</p>

</div>
<div class="parent">
  <div class="anotherclass">Another Random</div>
  <p class="item">Another item 1</p>
  <p class="item">Another item 2</p>
  <div>Random Text</div>
  <p class="item">Another item 3</p>

</div>
&#13;
&#13;
&#13;