DOM动态渲染元素后事件监听器不生效解决方案
问题根因
你的事件绑定逻辑执行时机早于异步渲染完成时间:renderCategories是异步函数,调用后不会阻塞后续代码执行,当你执行document.querySelectorAll('div.category-card')时,分类卡片还没被插入到DOM树中,自然选不到目标元素,事件绑定完全不生效。
可行解决方案
方案1:事件委托(优先推荐)
不需要等元素渲染完成,直接把事件绑定到页面初始加载时就已经存在的父容器.category-grid上,利用事件冒泡机制捕获子元素的点击事件,后续哪怕动态新增/删除分类卡片,也不需要重新绑定事件。
你只需要删掉原来写在renderCategories调用之后的那段事件绑定代码,替换为以下内容:
const categoryGrid = document.querySelector('.category-grid'); categoryGrid.addEventListener('click', (e) => { // 向上查找触发点击的分类卡片元素 const targetCard = e.target.closest('.category-card'); // 过滤掉容器空白区域的点击,避免误触发 if (!targetCard) return; console.log('Category clicked', targetCard.id); window.location.href = `movies.html?categoryId=${targetCard.id}`; });
方案2:渲染完成后再绑定事件
如果你不想用事件委托,可以把事件绑定逻辑移到renderCategories函数内部,等DOM元素全部插入到容器之后再执行绑定,修改后的完整index.js代码如下:
async function getCategories() { let url = 'http://localhost:8080/movieCategories'; try { let res = await fetch(url); return await res.json(); } catch (error) { console.log(error); } } async function renderCategories() { let categories = await getCategories(); let html = ''; categories.forEach(category => { let htmlSegment = ` <div class="category-card" id=${category.id}> <img src="./assets/images/sci-fi.jpg" alt="" class="card-img"> <div class="name">${category.name}</div> </div> `; html += htmlSegment; }); let container = document.querySelector('.category-grid'); container.innerHTML = html; // DOM插入完成后再绑定事件 container.querySelectorAll('div.category-card').forEach(row=>{ row.addEventListener('click',event=>{ console.log('Category clicked', event.currentTarget.id) window.location.href = 'movies.html?categoryId=' +event.currentTarget.id; }); }); } renderCategories();
小提示:页面跳转建议使用
window.location.href赋值,相比直接给window.location赋值写法更规范,兼容性更好。
内容的提问来源于stack exchange,提问作者User G Amsterdam
相关产品推荐
相关产品推荐

