首次开发Weather API应用:已显示城市天气重复展示问题排查求助
我正在开发我的首个Weather API应用,需求是:当查询的城市天气已在页面中显示时,页面应提示“You already know the weather”,且不重复展示该城市的天气信息。目前我的代码无法实现该功能,以下是我的完整代码,请帮忙排查其中存在的错误:
HTML代码
<div class="main"> <div class="container"> <div class="search_por"> <h2>Weather </h2> <div class="validate_msg color_white"></div> <form> <label for=""></label> <input type="search" class="input_text" value=""> <button type="submit" id="sub_button" class="srh_button">Search</button> </form> <!-- <canvas id="icon1" width="150" height="75"></canvas> --> <div class="dat_weather"> <ul id="list_it"> </ul> </div> </div> </div> </div>
JavaScript代码(原版本)
var get_text=document.querySelector("form"); get_text.addEventListener("submit",e=>{ e.preventDefault(); var input_val=document.querySelector('input').value; const apiKey="bc4c7e7826d2178054ee88fe00737da0"; const url=`https://api.openweathermap.org/data/2.5/weather?q=${input_val}&appid=${apiKey}&units=metric`; fetch(url,{method:'GET'}) .then(response=>response.json()) .then(data=>{console.log(data) const{main,sys,weather,wind}=data; //icons-end var error_ms=document.getElementsByClassName("validate_msg")[0]; var iconcode = weather[0].icon; console.log(iconcode); var li=document.createElement("Li"); var weatherinfo=` <div class="nameci font_40" data-name="${data.name},${sys.country}"> <span>${data.name}</span> <sup>${sys.country}</sup> </div> <div class="temp_ic"> <img class="weat_icon" src="http://openweathermap.org/img/w/${iconcode}.png"> <div class="deg">${Math.floor( main.temp )}<sup>o</sup></div> </div> <div class="clear"> <div>${weather[0].description}</div> </div> `; li.innerHTML=weatherinfo; var ulid=document.getElementById("list_it"); ulid.appendChild(li); var city_name=data.name; console.log(skycons); var listitems=document.querySelectorAll('#list_it'); const listArray=Array.from(listitems); if(listArray.length>0) { var filtered_array=listArray.filter(el=>{ let content=""; if(input_val.includes(',')) { if(input_val.split(',')[1].length>2) { alert("hving 2 commos"); inputval=input_val.split(',')[0]; content=el.querySelector(".nameci span").textContent.toLowerCase(); //content=el.querySelector(".nameci").innerHTML.toLowerCase(); //content=inputval.toLowerCase(); } else { content=el.querySelector(".nameci").dataset.name.toLowerCase(); } alert(filtered_array); } else { content=el.querySelector(".nameci span").textContent.toLowerCase(); } console.log(inputval.toLowerCase()); return inputval.toLowerCase(); }); if(filtered_array.length>0) { console.log(filtered_array.length); error_ms.innerHTML="You Already know the weather of this country...."; get_text.reset(); return; } } }) .catch((error)=>{ error_ms.innerHTML="Please Enter a valid city Name"; }); var error_ms=document.getElementsByClassName("validate_msg")[0]; error_ms.innerHTML=""; //var get_text=document.querySelector("form"); get_text.reset(); });
错误排查与修复说明
我来帮你梳理下代码里的关键问题,这些问题导致重复提示功能失效:
变量名拼写错误:代码里多次使用
inputval但实际定义的变量是input_val,这会触发未定义错误,比如console.log(inputval.toLowerCase());这行,必须统一改成input_val。列表项选择器错误:
document.querySelectorAll('#list_it')选中的是整个<ul>容器,而非里面的每个城市<li>项,应该修改为document.querySelectorAll('#list_it li'),这样才能遍历已添加的城市条目。筛选逻辑错误:
filter回调函数的return语句逻辑错误,你现在返回的是输入值,而应该比较当前列表项的城市名与输入的城市名是否相等,这样才能筛选出已存在的重复项。检查顺序不合理:原代码是先请求API拿到数据后才检查是否重复,这会导致先添加重复项再提示,还浪费了API请求。正确的逻辑应该是在发起fetch请求之前就检查是否已存在该城市。
冗余的alert干扰:代码里的
alert(filtered_array);和alert("hving 2 commos");会打断用户流程,建议移除这些调试用的弹窗。
修复后的JavaScript代码
var get_text = document.querySelector("form"); var error_ms = document.getElementsByClassName("validate_msg")[0]; var ulid = document.getElementById("list_it"); get_text.addEventListener("submit", e => { e.preventDefault(); var input_val = document.querySelector('input').value.trim().toLowerCase(); if (!input_val) { error_ms.innerHTML = "Please enter a city name"; return; } // 先检查是否已存在该城市 let isDuplicate = false; const listItems = document.querySelectorAll('#list_it li'); listItems.forEach(item => { let existingCity = ""; if (input_val.includes(',')) { // 处理带国家代码的输入 existingCity = item.querySelector(".nameci").dataset.name.toLowerCase(); } else { existingCity = item.querySelector(".nameci span").textContent.toLowerCase(); } // 比较输入值和已存在的城市名 if (input_val.includes(existingCity) || existingCity.includes(input_val)) { isDuplicate = true; } }); if (isDuplicate) { error_ms.innerHTML = "You already know the weather"; get_text.reset(); return; } // 检查通过,发起API请求 const apiKey = "bc4c7e7826d2178054ee88fe00737da0"; const url = `https://api.openweathermap.org/data/2.5/weather?q=${input_val}&appid=${apiKey}&units=metric`; fetch(url, { method: 'GET' }) .then(response => { if (!response.ok) throw new Error("City not found"); return response.json(); }) .then(data => { const { main, sys, weather } = data; var iconcode = weather[0].icon; var li = document.createElement("li"); var weatherinfo = ` <div class="nameci font_40" data-name="${data.name},${sys.country}"> <span>${data.name}</span> <sup>${sys.country}</sup> </div> <div class="temp_ic"> <img class="weat_icon" src="http://openweathermap.org/img/w/${iconcode}.png"> <div class="deg">${Math.floor(main.temp)}<sup>o</sup></div> </div> <div class="clear"> <div>${weather[0].description}</div> </div> `; li.innerHTML = weatherinfo; ulid.appendChild(li); error_ms.innerHTML = ""; get_text.reset(); }) .catch((error) => { error_ms.innerHTML = "Please Enter a valid city Name"; }); });
内容的提问来源于stack exchange,提问作者web_in

