API调用求助:页面加载正常但搜索结果无法正确展示
问题分析与解决方案
我帮你排查了一下,搜索功能失效主要有两个核心问题,咱们一步步解决:
1. API返回数据结构不匹配
TVMaze的搜索接口(/search/shows)返回的数组结构和剧集列表接口(/shows)不一样!搜索接口返回的是包含show属性的对象数组,每个元素是{ show: 剧集信息对象, score: 匹配分数 },而你在渲染时直接用show.image、show.name,这会导致无法读取到正确的属性,自然渲染不出内容。
2. 事件触发时机不合理
你用了keydown事件,这会在用户每按下一个按键时就发起请求(比如输入"abc"会发3次请求),不仅浪费资源,还可能导致页面频繁刷新。更合理的做法是监听keyup事件,并且只在用户按下回车键时发起搜索,或者做防抖处理(避免频繁请求)。
修正后的完整代码
JavaScript部分
// 展示评分最高的10部剧集 fetch('https://api.tvmaze.com/shows') .then(blob => blob.json()) .then(json => { // 修正slice:slice(0,10)才是取前10个,之前的slice(0,9)只有9个 const topTenShows = json .filter(show => show.rating.average) .sort((a, b) => b.rating.average - a.rating.average) // 简化排序逻辑 .slice(0, 10) return topTenShows }) .then(shows => renderShows(shows)) // 抽离渲染逻辑,复用代码 // 抽离渲染函数,避免重复代码 function renderShows(shows) { const app = document.getElementById('app') app.innerHTML = shows.map(show => ` <div class="col-sm movie-content"> <!-- 用可选链处理图片不存在的情况,避免报错 --> <img src="${show.image?.medium || ''}"> <div class="movie-info"> <h5>${show.name}</h5> <span>Rating: ${show.rating.average}</span> <br /> <span>Genres: ${show.genres.join(', ')}</span> <!-- 修正文字:把Rating改成Genres,更准确 --> </div> </div> `).join('') // join()不传参数会默认加逗号,传空字符串避免多余分隔符 } // 搜索功能 function searchTvAmaze (event) { // 只在按下回车键时发起搜索 if (event.key !== 'Enter') return const searchQuery = event.target.value.trim() // 如果搜索框为空,返回展示top10 if (!searchQuery) { fetch('https://api.tvmaze.com/shows') .then(blob => blob.json()) .then(json => { const topTenShows = json .filter(show => show.rating.average) .sort((a, b) => b.rating.average - a.rating.average) .slice(0, 10) renderShows(topTenShows) }) return } fetch(`https://api.tvmaze.com/search/shows?q=${encodeURIComponent(searchQuery)}`) // 用encodeURIComponent处理特殊字符 .then(blob => blob.json()) .then(searchResults => { // 提取出每个结果里的show对象 const shows = searchResults.map(item => item.show) renderShows(shows) }) .catch(err => console.error('搜索出错:', err)) // 添加错误捕获,方便调试 } const inputSearchField = document.querySelector('.inputSearchField') inputSearchField.addEventListener('keyup', searchTvAmaze) // 改成keyup事件
HTML部分(无需修改,保持原样)
<div class="col-sm-10 main-content"> <div class="search"> <input class="inputField inputSearchField" type="text" placeholder="Search..."> </div> <div class="container"> <div id="app" class="row"> </div> </div> </div>
关键修改点说明
- 统一渲染逻辑:抽离
renderShows函数,避免重复编写DOM渲染代码,后续维护更方便。 - 适配搜索API结构:搜索结果通过
searchResults.map(item => item.show)提取出真正的剧集对象,再传给渲染函数。 - 优化事件触发:改成
keyup事件并判断回车键,避免不必要的请求;同时处理搜索框为空的情况,返回展示top10剧集。 - 容错处理:用可选链
show.image?.medium处理图片不存在的情况,避免控制台报错;添加catch捕获请求错误。 - 细节优化:排序逻辑简化为
b.rating.average - a.rating.average;join('')避免渲染时出现多余逗号;用encodeURIComponent处理搜索关键词里的特殊字符(比如空格、中文等)。
内容的提问来源于stack exchange,提问作者Lacon
相关产品推荐
相关产品推荐

