You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

电影搜索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>

关键改进点

  1. 数据与容器一一绑定:通过data.forEach((item, index),将第index个电影数据对应到第index个容器,避免了批量操作所有元素的错误
  2. 搜索前重置状态:每次搜索前隐藏所有容器并清空内部内容,防止旧数据残留
  3. 边界处理:当API返回结果超过预设容器数量时,停止赋值;处理无图片、无评分的异常情况
  4. 布局优化:将顶部banner设为固定定位,调整输入框和按钮的位置,避免页面滚动时的布局错乱

内容的提问来源于stack exchange,提问作者FrankDiCostanzo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 17:18:09