点击无序列表子元素时indexOf返回-1,如何获取正确li索引?
问题
尝试从HTML的ul元素中获取其子元素li的索引值,通过[...ul.children]将ul的子元素转换为数组。但点击子元素时,返回的索引值始终为-1而非正确值,是否因为li内部包含div等嵌套元素导致的?
原代码
JavaScript
const ul = document.querySelector('ul'); ul.addEventListener('click', myFunc); function myFunc(e) { const indexToShow = [...ul.children].indexOf(e.target); console.log(indexToShow); console.log(e.target); }
HTML
<ul class="calendar-list"> <li class="list-item"> <div class="fight-link"> <span class="date">1 Dec 2022</span> <span class="fighters-name">JAY</span> </div> </li> <li class="list-item"> <div class="fight-link"> <span class="date">2 Dec 2022</span> <span class="fighters-name">Jo</span> </div> </li> <li class="list-item"> <div class="fight-link"> <span class="date">3 Dec 2022</span> <span class="fighters-name">Bob</span> </div> </li> </ul>
解决方案
没错,问题根源就是点击事件的e.target指向的是你实际点击的嵌套元素(比如div、span),而非父级li元素,而ul.children仅包含li元素,所以用嵌套元素在数组中查找,必然返回-1。
以下两种修复方法:
方法一:事件委托+closest()定位父级li
适合li动态增删的场景,通过事件委托在ul上,再找到点击元素对应的li父节点:
const ul = document.querySelector('ul'); ul.addEventListener('click', myFunc); function myFunc(e) { // 向上查找最近的li元素 const targetLi = e.target.closest('li'); if (!targetLi) return; // 点击ul空白区域时直接返回,避免报错 const indexToShow = [...ul.children].indexOf(targetLi); console.log(indexToShow); console.log(targetLi); }
closest('li')会从当前点击的元素开始向上遍历DOM树,返回第一个匹配的li元素,完美解决嵌套元素的问题。
方法二:直接给li绑定点击事件
适合静态列表(li不会动态变化),遍历li时直接拿到索引:
const lis = document.querySelectorAll('li'); lis.forEach((li, index) => { li.addEventListener('click', () => { console.log(index); console.log(li); }); });
这种方式无需额外查找,直接在遍历过程中获取索引,逻辑更简洁。
内容的提问来源于stack exchange,提问作者Pro Girl
相关产品推荐
相关产品推荐

