获取兄弟姐妹之间的元素索引,忽略具有特定孩子的兄弟姐妹

问题描述 投票:0回答:5

我有一个特定的用例,但我似乎找不到答案。给定以下 DOM 元素:

<div class="wrapper">
   <div class="item"></div>
   <div class="item">
       <div class="foo"></div>
   </div>
   <div class="item">
       <div class="bar"></div>
   </div>
   <div class="item"></div>
   <div class="item selected"></div>
   <div class="item"></div>
</div>

我需要找到

.selected
元素与其兄弟元素的索引。但我需要忽略任何具有
.foo
子元素的兄弟元素(它只会是直接子元素)。

因此,通常要查找

.item .selected
的索引,您可以使用
$(".item.selected").index()
给出 4,但由于它之前的一项有
.foo
子项,所以正确答案是 3

我想,最好的方法是获取所选元素之前的所有兄弟姐妹(因为之后的兄弟姐妹不会移动它的索引),然后计算有多少个有.foo

子元素,然后减去它所选索引中的数字,因此 
4-1=3。我尝试这样做:

var selectedIndex = $(".item.selected").index(); var fooCount = $(".item.selected").prevAll('.item > .foo').length; var finalIndex = selectedIndex - fooCount;

问题是,fooCount 即将出现

0 而不是 3

javascript jquery
5个回答
2
投票
您可以简单地使用

.filter()

 并删除前面具有给定子元素的元素。

const selected = $('.selected'); const foos = selected.prevAll().filter(function() { return !($(this).find('.foo').length); }); console.log(selected.index(), foos.length);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
  <div class="item"></div>
  <div class="item">
    <div class="foo"></div>
  </div>
  <div class="item">
    <div class="bar"></div>
  </div>
  <div class="item"></div>
  <div class="item selected"></div>
  <div class="item"></div>
</div>


0
投票
使用此选择器

".item:not(:has(.foo))"

,然后循环查找特定索引。

var index = $(".item:not(:has(.foo))") .toArray() .findIndex(function(item) { return $(item).hasClass('selected'); }); console.log(index);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
  <div class="item"></div>
  <div class="item">
    <div class="foo"></div>
  </div>
  <div class="item">
    <div class="bar"></div>
  </div>
  <div class="item"></div>
  <div class="item selected"></div>
  <div class="item"></div>
</div>


0
投票
你很接近。

改变:

var fooCount = $(".item.selected").prevAll('.item > .foo').length;

…至:

var fooCount = $(".item.selected").prevAll('.item:has(.foo)').length;

否则,您正在寻找一个具有

.foo 类别的 兄弟姐妹

,而您实际上想要一个具有 
.foo 类别的 孩子
 的兄弟姐妹。

片段:

var selectedIndex = $(".item.selected").index(); var fooCount = $(".item.selected").prevAll('.item:has(.foo)').length; var finalIndex = selectedIndex - fooCount; console.log(finalIndex);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
   <div class="item"></div>
   <div class="item">
       <div class="foo"></div>
   </div>
   <div class="item">
       <div class="bar"></div>
   </div>
   <div class="item"></div>
   <div class="item selected"></div>
   <div class="item"></div>
</div>


0
投票
您可以组合:

:not():选择与给定选择器不匹配的所有元素。

:has():将匹配元素的集合减少到具有与选择器或 DOM 元素匹配的后代的元素。

:index(element):其中 element 是要查找的 DOM 元素或 jQuery 对象中的第一个元素。

因此,您可以更改代码:

var selectedIndex = $(".item.selected").index();

至:

var selectedIndex = $('.item:not(:has(.foo))').index($('.item.selected'));

var selectedIndex = $('.item:not(:has(.foo))').index($('.item.selected')); console.log(selectedIndex );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


<div class="wrapper">
    <div class="item"></div>
    <div class="item">
        <div class="foo"></div>
    </div>
    <div class="item">
        <div class="bar"></div>
    </div>
    <div class="item"></div>
    <div class="item selected"></div>
    <div class="item"></div>
</div>


0
投票
JavaScript 解决方案比 jQuery 解决方案更直接:

不忽略特定的兄弟姐妹:

Array.from(element.parentElement.children).indexOf(element);
忽略特定的兄弟姐妹:

Array.from(element.parentElement.children).filter((sibling) => !sibling.querySelector(':scope > .foo')).indexOf(element); // ":scope" just selects the 'sibling' element
这是工作代码:

let element = document.querySelector('.wrapper .item.selected'); let allSiblings = Array.from(element.parentElement.children); let filteredSiblings = allSiblings.filter((sibling) => !sibling.querySelector(':scope > .foo')); console.log('Sibling Index: ' + allSiblings.indexOf(element)); console.log('Filtered Sibling Index: ' + filteredSiblings.indexOf(element));
<div class="wrapper">
  <div class="item"></div>
  <div class="item">
    <div class="foo"></div>
  </div>
  <div class="item">
    <div class="bar"></div>
  </div>
  <div class="item"></div>
  <div class="item selected"></div>
  <div class="item"></div>
</div>

一切都已经有完整的浏览器支持很长时间了,唯一的问题是

:scope

 但自 2014 年 9 月以来就得到了全面支持,如果可以像其他答案一样用 
.item > .foo
 替换...但可能会导致问题,如果您在某个时候已经嵌套了 
.item
 孩子。

您也可以将

Array.from(children)

 替换为 
[...children]

© www.soinside.com 2019 - 2024. All rights reserved.