如何仅让父li控制开关切换,避免嵌套子li触发该切换事件?
解决筛选器父/子li点击冲突问题
我给筛选器的父li写了展开/收起的toggle代码,但点击嵌套在父li内的子li时,也会触发父li的开关切换。需要实现仅父li控制展开/收起,子li点击不触发该操作,且不能通过类名定位元素。
解决方案
问题根源是事件冒泡:点击子元素时,事件会向上传递到父元素,触发父元素的事件逻辑。以下两种方案无需依赖特定类名,仅通过元素结构关系解决冲突:
方案一:精准判断触发目标
只在点击父li本身或其直接子标题(如h4)时执行toggle操作,点击子li时不触发:
let filterLi = document.querySelectorAll('.searchandfilter ul li') let filterLiOpen = []; filterLi.forEach((tag, index) => { // 仅给包含子ul的父li绑定事件 if (tag.querySelector('ul')) { tag.addEventListener('click', (event) => { // 判断点击目标是否为父li本身,或父li的直接子元素(如标题h4) if (event.target === tag || (tag.contains(event.target) && event.target.parentElement === tag)) { tag.classList.toggle('active') filterLiOpen[index] = !filterLiOpen[index] console.log(filterLiOpen); } }) } })
方案二:阻止子li的事件冒泡
给子li添加点击事件,阻止事件向上传递到父li:
let filterLi = document.querySelectorAll('.searchandfilter ul li') let filterLiOpen = []; filterLi.forEach((tag, index) => { if (tag.querySelector('ul')) { // 父li绑定展开/收起逻辑 tag.addEventListener('click', () => { tag.classList.toggle('active') filterLiOpen[index] = !filterLiOpen[index] console.log(filterLiOpen); }) } else { // 子li绑定事件,阻止冒泡到父li tag.addEventListener('click', (event) => { event.stopPropagation() }) } })
方案说明
- 方案一通过校验点击目标,只允许父li本身或它的直接子标题触发展开/收起,逻辑更精准。
- 方案二直接阻止子li的事件向上冒泡,实现起来更简单直接。
内容的提问来源于stack exchange,提问作者k-lythgoe
相关产品推荐
相关产品推荐

