动态创建子元素点击时无法正确获取对应标题的问题求助
问题
我有一个async函数用于生成若干元素,点击元素时想要在控制台打印该元素的标题,但使用e.target时总是返回第一个元素的标题。以下是我的HTML和JavaScript代码:
HTML代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>HomeChow</title> <link rel="stylesheet" href="style.css" /> <!-- Fonts --> <link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> <link href="https://fonts.googleapis.com/css2?family=Pacifico&display=swap" rel="stylesheet" /> <link href="https://fonts.googleapis.com/css2?family=Exo:wght@500&display=swap" rel="stylesheet" /> </head> <body> <!-- Hero Section --> <div class="hero"> <nav class="navbar"> <div class="logo">HomeChow</div> <div class="menu"> <ul> <li>Shop</li> <li>Features</li> <li>Recipes</li> <li>Hotline</li> </ul> </div> <div class="sigin_signup"> <p class="login">Login</p> <p class="signup">SignUp</p> </div> </nav> </div> <!-- Main Content --> <div class="main_content"> <!-- Search Row --> <div class="search_row"> <p id="search_title">Recipe</p> <input type="text" class="" id="search_bar" placeholder="Search Recipes and Ingredients" /> <div id="sort_by"> <select> <option value="newest">Sort by: newest</option> <option value="oldest">Sort by: oldest</option> </select> </div> </div> <!-- Categories --> <div class="details_row"> <div class="main_content_menu"> <div class="categories"> <div class="menu_items"> <button class="menu_btn" id="breakfast" data-category="Breakfast"> Breakfast </button> <button class="menu_btn" id="dessert" data-category="Dessert"> Dessert </button> <button class="menu_btn" id="miscellaneous" data-category="Miscellaneous" > Miscellaneous </button> <button class="menu_btn" id="pasta" data-category="Pasta"> Pasta </button> <button class="menu_btn" id="seafood" data-category="Seafood"> Seafood </button> <button class="menu_btn" id="side" data-category="Side"> Side </button> <button class="menu_btn" id="starter" data-category="Starter"> Starter </button> <button class="menu_btn" id="vegan" data-category="Vegan"> Vegan </button> <button class="menu_btn" id="vegetarian" data-category="Vegetarian" > Vegetarian </button> </div> </div> </div> <!-- FILTER BY CATEGORY --> <div class="column2"> </div> <!--END OF FILTER BY CATEGORY --> <div class="footer"></div> <script src="./app.js"></script> </body> </html>
JavaScript代码
let column2 = document.querySelector(".column2"); //Other working functions here // Selecting an option from the results -- The issue!! column2.addEventListener("click", (e) => { console.log("column 2 clicked"); if (e.target.classList.contains("category_food_search_results")) { const foodDetailsContainer = document.querySelector( ".category_food_details" ); const foodTitle = foodDetailsContainer.querySelector( ".category_food_title" ); console.log(foodTitle.textContent); }});
原因分析
问题出在document.querySelector(".category_food_details")方法上——它只会返回页面中匹配该选择器的第一个元素。不管点击的是哪一个生成的元素,代码都会去取页面里第一个.category_food_details容器中的标题,自然每次打印的都是第一个元素的内容。
解决方案
要获取点击元素对应的标题,需要基于当前点击的目标元素,向上查找它所属的.category_food_details容器,再在这个容器内获取标题。可以使用Element.closest()方法实现:
let column2 = document.querySelector(".column2"); column2.addEventListener("click", (e) => { console.log("column 2 clicked"); if (e.target.classList.contains("category_food_search_results")) { // 从点击的元素向上找最近的.category_food_details容器 const foodDetailsContainer = e.target.closest(".category_food_details"); if (foodDetailsContainer) { // 确保找到容器后再执行 const foodTitle = foodDetailsContainer.querySelector(".category_food_title"); console.log(foodTitle?.textContent); // 可选链避免找不到标题时报错 } } });
关键改动说明
- 用
e.target.closest(".category_food_details")替代document.querySelector(".category_food_details"):closest()会从当前元素开始向上遍历DOM树,找到第一个匹配选择器的祖先元素,精准定位到点击元素所属的容器。 - 添加存在性检查:避免因DOM结构变化或元素不存在导致的报错,让代码更健壮。
内容的提问来源于stack exchange,提问作者Martin
相关产品推荐
相关产品推荐

