如何修复overlay弹窗点击任意电影仅显示最后一部电影信息的问题
问题原因分析
- 事件重复绑定:你在
map循环每生成一个电影卡片,就调用document.querySelectorAll(".seemore")选中页面所有已生成的「See more」按钮,给所有旧按钮重复叠加绑定点击事件,最终单个按钮会被绑定N次(N等于遍历到当前的电影序号),点击一次会触发多次弹窗生成逻辑。 - 变量引用的闭包问题:点击事件的回调是异步触发的,等你实际点击按钮时,
map循环已经执行完毕,回调里引用的movie变量已经指向循环的最后一个电影对象,所以所有弹窗都只展示最后一部电影的信息。 - 冗余DOM隐患:你每次点击都用
innerHTML +=往pageContainer里加弹窗,多次点击后页面会残留大量无用的弹窗DOM节点。
修复方案
调整逻辑为「先批量生成所有电影DOM,再统一绑定事件,同时把对应电影信息存在按钮的自定义属性上,点击时直接从当前触发事件的按钮上取对应信息」,修复后的代码如下:
const movieIntegration = () => { // 先批量生成所有电影的DOM结构 allMovies.forEach(movie => { movieGallery.innerHTML += `<div class="imgContainer"> <img src="${movie.img}" alt="${movie.name}"> <div class="titleContainer"> <div class="movieTitle"> ${movie.name} </div> <!-- 把当前电影信息存在按钮的自定义属性里,需要其他字段可同理新增data-xxx属性 --> <div class="seemore" data-movie-name="${movie.name}" data-movie-img="${movie.img}"> See more </div> </div> </div>` }) // 所有DOM生成完成后,统一给所有seemore按钮绑定一次点击事件 const seemoreBtns = document.querySelectorAll(".seemore") seemoreBtns.forEach(btn => { btn.addEventListener("click", () => { // 从当前点击的按钮的自定义属性里取对应电影的信息 const currentMovieName = btn.dataset.movieName // 先清空之前可能存在的旧弹窗,避免DOM冗余 const oldPopup = document.querySelector(".popupContainer") if(oldPopup) oldPopup.remove() pageContainer.innerHTML += `<div class="popupContainer"> <div class="popup"> ${currentMovieName} <div id="likeButton"> <img src="img/like.png"> </div> <div id="editButton"> <img src="img/edit.png"> </div> <a href="submit.html"> <div id="addingButton"> <img src="img/add.png"> </div> </a> </div> </div>` }, true) }) }
额外优化建议
- 如果需要传递更多电影信息,直接在
seemore按钮上新增对应的data-自定义属性即可,取值时通过btn.dataset.xxx读取,属性名会自动转驼峰命名,比如data-movie-date对应btn.dataset.movieDate。 - 可自行补充弹窗关闭逻辑,比如点击弹窗外部区域直接移除弹窗DOM即可。
内容的提问来源于stack exchange,提问作者Saantuu
相关产品推荐
相关产品推荐

