我有一个特定的用例,但我似乎找不到答案。给定以下 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。
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>
".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>
改变:
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>
: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>
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]
。