Vanilla JS中event.target.querySelectorAll('ul')返回空NodeList问题
为什么
event.target.querySelectorAll('ul')会返回空NodeList? 咱们先拆解清楚问题出在哪:
核心原因
event.target指向的是实际被点击的元素,不是你以为的那个包含子菜单的父li。
看你的HTML结构,最外层的li没有任何文本内容,只有一个嵌套的ul。当你点击这个区域时,实际触发点击的是内部的ul或者ul里的子li,而不是最外层的li本身:- 如果点击的是
ul,event.target.tagName是UL,你的代码会直接return,根本不会执行到console.log那一行。 - 如果点击的是子
li(比如"Sub menu item 1"),event.target就是这个子li,它本身没有嵌套ul,所以querySelectorAll('ul')自然返回空NodeList。
- 如果点击的是
querySelectorAll('ul')的查找范围是目标元素的后代节点
只有当event.target对应的li内部确实嵌套了ul时,这个方法才会返回结果。如果点击的li本身没有子菜单,结果肯定是空。
满足你需求的解决方案
你的目标是:点击任意li时,检查它是否包含子菜单(ul),存在则添加open类。这里推荐用closest('li')来精准定位被点击的li,不管你点击的是li本身还是它内部的元素:
var clickHandler = function(event){ event.preventDefault(); // 获取点击位置对应的最近的li元素(不管点击的是li内部的什么内容) const clickedLi = event.target.closest('li'); if(!clickedLi) return; // 检查该li是否包含子ul(只要存在一个就会返回对应元素,否则返回null) const hasSubmenu = clickedLi.querySelector('ul') !== null; if(hasSubmenu){ // 用toggle实现开关效果,也可以直接用add添加类 clickedLi.classList.toggle('open'); } } document.addEventListener('DOMContentLoaded', function() { var menu = document.getElementById('menu'); menu.addEventListener('click', clickHandler, false); });
为什么这个方案可行?
closest('li')会从点击的元素开始向上遍历DOM树,找到最近的li祖先,完美解决了“点击子元素无法定位到父li”的问题。querySelector('ul')比querySelectorAll更适合这个场景:我们只需要知道是否存在子菜单,它会返回第一个匹配的ul元素,不存在则返回null,判断起来更高效。
内容的提问来源于stack exchange,提问作者Emeka Mbah
相关产品推荐
相关产品推荐

