电影搜索APP开发问题:循环仅返回数组最后一个值,append返回全部值
问题分析与修复
我正在开发一款电影搜索应用,期望输入框输入内容后,展示包含标题、图片和评分的所有容器。当前点击搜索按钮时,尝试为标题赋予API返回的数组数据,遇到两个问题:
- 使用for循环遍历数组时,所有标题仅显示最后一个值
- 使用append方法时,每个标题都会显示所有数组值
问题根源
原代码的核心错误在于:遍历API返回的电影名称数组时,每次循环都对所有标题元素执行append/赋值操作。比如循环到第i个电影名时,会把这个名字加到每一个标题里,最终每个标题都累积了所有电影名;如果用innerHTML = names,则每次循环都会覆盖所有标题的内容,最后所有标题都变成最后一个电影名。
正确的逻辑应该是将数组的第i个元素对应到第i个标题元素,同时还要处理容器的显示/隐藏(比如API返回结果数量少于预设容器时,隐藏多余容器),以及每次搜索前清空旧内容。
修复后的代码
JavaScript
const moviesCtn = document.querySelectorAll('.jsMovieFlex'); const input = document.querySelector('#inpText'); const button = document.querySelector('#btn'); button.addEventListener('click', () => { const inpValue = input.value.trim(); // 先隐藏所有容器,后续根据返回结果显示对应数量的容器 moviesCtn.forEach(ctn => { ctn.style.display = 'none'; // 清空容器内的旧内容 const title = ctn.querySelector('.title-movie'); const img = ctn.querySelector('.jsMovieImage'); const rate = ctn.querySelector('h3'); title.textContent = ''; img.style.backgroundImage = ''; rate.textContent = 'rate'; }) if (inpValue) { searchMovie(`https://api.tvmaze.com/search/shows?q=${inpValue}`); } }) const searchMovie = async(url) => { const req = await fetch(url); const data = await req.json(); // 遍历返回的结果,一一对应到容器 data.forEach((item, index) => { if (index >= moviesCtn.length) return; // 超出预设容器数量则停止 const ctn = moviesCtn[index]; const title = ctn.querySelector('.title-movie'); const img = ctn.querySelector('.jsMovieImage'); const rate = ctn.querySelector('h3'); // 填充数据 title.textContent = item.show.name; // 设置海报图片(处理无图片的情况) if (item.show.image?.medium) { img.style.backgroundImage = `url(${item.show.image.medium})`; img.style.backgroundSize = 'cover'; img.style.backgroundPosition = 'center'; } else { img.style.background = 'darkred'; } // 设置评分(处理无评分的情况) rate.textContent = item.show.rating.average ? `评分: ${item.show.rating.average}` : '暂无评分'; // 显示当前容器 ctn.style.display = 'flex'; }) }
CSS
body { width: 100%; min-height: 100vh; background: #151c3f; display: flex; flex-wrap: wrap; justify-content: center; gap: 50px; overflow-x: hidden; margin: 0; padding-top: 500px; /* 给顶部banner留出空间 */ } .main { position: fixed; top: 0; left: 0; width: 100%; height: 500px; background: url(avengers-endgame-locandina-Sentieri.jpg); background-repeat: no-repeat; background-position: top; background-size: cover; } .main h1 { color: #fff; position: absolute; width: 100%; text-align: center; font-size: 5rem; font-family: Georgia, 'Times New Roman', Times, serif; font-weight: 300; letter-spacing: 1px; z-index: 1; margin: 0; top: 20%; } .main>input { position: absolute; z-index: 1; top: 50%; left: 50%; transform: translate(-50%, -50%); padding: 20px; font-size: 22px; outline: none; border: none; border-radius: 10px; box-shadow: 20px 20px 5px #00000096; } .main>button { position: absolute; z-index: 1; top: 65%; left: 50%; transform: translateX(-50%); font-size: 18px; padding: 10px 20px; letter-spacing: 1px; border-radius: 7px; outline: none; border: none; cursor: pointer; } .main::after { position: absolute; content: ""; inset: 0; background: #0000006e; } .movie-container { position: relative; width: 400px; height: 300px; background: #fff; display: none; justify-content: center; align-items: center; } .movie-container>h1 { position: absolute; width: 100%; transform: translateY(-30%); align-self: flex-start; text-align: center; font-size: 1.5rem; margin: 0; } .movie-container>h3 { font-size: 20px; position: absolute; bottom: 5px; margin: 0; } .movie-container>.movie-image { width: 70%; height: 70%; background: darkred; background-size: cover; background-position: center; }
HTML
<div class="main"> <h1>Search Movie App</h1> <input type="text" id="inpText" placeholder="Search Movie"> <button id="btn">Click Here</button> </div> <div class="movie-container jsMovieFlex"> <h1 class="title-movie"></h1> <div class="movie-image jsMovieImage"></div> <h3>rate</h3> </div> <div class="movie-container jsMovieFlex"> <h1 class="title-movie"></h1> <div class="movie-image jsMovieImage"></div> <h3>rate</h3> </div> <div class="movie-container jsMovieFlex"> <h1 class="title-movie"></h1> <div class="movie-image jsMovieImage"></div> <h3>rate</h3> </div> <div class="movie-container jsMovieFlex"> <h1 class="title-movie"></h1> <div class="movie-image jsMovieImage"></div> <h3>rate</h3> </div> <div class="movie-container jsMovieFlex"> <h1 class="title-movie"></h1> <div class="movie-image jsMovieImage"></div> <h3>rate</h3> </div> <div class="movie-container jsMovieFlex"> <h1 class="title-movie"></h1> <div class="movie-image jsMovieImage"></div> <h3>rate</h3> </div> <div class="movie-container jsMovieFlex"> <h1 class="title-movie"></h1> <div class="movie-image jsMovieImage"></div> <h3>rate</h3> </div> <div class="movie-container jsMovieFlex"> <h1 class="title-movie"></h1> <div class="movie-image jsMovieImage"></div> <h3>rate</h3> </div> <div class="movie-container jsMovieFlex"> <h1 class="title-movie"></h1> <div class="movie-image jsMovieImage"></div> <h3>rate</h3> </div> <div class="movie-container jsMovieFlex"> <h1 class="title-movie"></h1> <div class="movie-image jsMovieImage"></div> <h3>rate</h3> </div>
关键改进点
- 数据与容器一一绑定:通过
data.forEach((item, index),将第index个电影数据对应到第index个容器,避免了批量操作所有元素的错误 - 搜索前重置状态:每次搜索前隐藏所有容器并清空内部内容,防止旧数据残留
- 边界处理:当API返回结果超过预设容器数量时,停止赋值;处理无图片、无评分的异常情况
- 布局优化:将顶部banner设为固定定位,调整输入框和按钮的位置,避免页面滚动时的布局错乱
内容的提问来源于stack exchange,提问作者FrankDiCostanzo
相关产品推荐
相关产品推荐

