点击option类嵌套元素报Cannot read properties of undefined如何解决
错误原因
- 事件目标取值错误:你点击
.option内部嵌套的图片、文字等子元素时,event.target指向的是被点击的子元素本身,子元素内部没有ion-icon节点,getElementsByTagName('ion-icon')[0]返回undefined,调用classList属性就会抛出你遇到的错误。 - 全局计数器逻辑不合理:全局共用一个
counter变量,只能实现所有菜单统一切换,无法支持每个分类单独控制展开/收起。 - 批量操作所有食物项不符合常规菜单逻辑:现有代码会同时切换所有
.food-item的显隐,一般菜单是点击对应分类只展开该分类下的内容。
修复方案
把事件目标换成绑定事件的.option元素本身(用event.currentTarget),同时去掉全局计数器,直接根据箭头的类名判断当前状态,也可以根据需求调整为单个分类控制对应内容:
const options = document.querySelectorAll(".option"); options.forEach(function(option) { option.addEventListener("click", function(event) { // 用currentTarget获取绑定事件的.option元素,不受点击子元素影响 const currentOption = event.currentTarget; const currentArrow = currentOption.querySelector('.dropdown-arrow'); // 不需要全局counter,直接判断当前箭头的状态 const isExpanded = currentArrow.classList.contains('rotate-on'); if (!isExpanded) { currentArrow.classList.add('rotate-on'); currentArrow.classList.remove('rotate-off'); // 如果要全局展开所有foodItem保留下面这段,如果要单个分类控制就替换成对应逻辑 document.querySelectorAll('.food-item').forEach(food => { food.classList.remove('hidden'); }); // 单个分类控制对应内容的写法示例:获取当前option后面的foodItem直到下一个option /* let nextNode = currentOption.nextElementSibling; while(nextNode && !nextNode.classList.contains('option')){ if(nextNode.classList.contains('food-item')){ nextNode.classList.remove('hidden'); } nextNode = nextNode.nextElementSibling; } */ } else { currentArrow.classList.add('rotate-off'); currentArrow.classList.remove('rotate-on'); // 全局收起 document.querySelectorAll('.food-item').forEach(food => { food.classList.add('hidden'); }); // 单个分类收起对应内容的写法和上面同理 } }); });
如果你只需要全局统一切换所有内容的显隐,用上面的代码就可以直接解决报错问题;如果需要每个分类单独控制自己的下属内容,就把注释里的单个分类控制逻辑放开,把全局操作的代码删掉即可。
内容的提问来源于stack exchange,提问作者Noah Gallego
相关产品推荐
相关产品推荐

