如何使用JavaScript localStorage为天气应用实现搜索保存功能
问题排查
你现有代码存在5个直接导致功能失效的问题:
- DOM选择器不匹配:JS中获取
id="searcher"的搜索框,但HTML里搜索框没有加对应id,取到的元素是null - 事件监听无效:绑定的
history不是浏览器原生事件,点击按钮无法触发存历史的逻辑 - localStorage键名不一致:存储历史时用的键是
historyList,删除历史时错写成histories,会导致删除操作后数据错乱 - 历史条目无交互:没有给历史项绑定点击查天气、触发删除的事件,功能无法实际使用
- 初始化无兼容判断:读取本地历史时没做空值校验,首次打开页面无历史记录时会直接报错
- 无自动存历史逻辑:搜索成功后不会自动写入记录,也没做重复城市去重、历史条数限制
完整修正方案
修正后的HTML代码
补全缺失的元素id,修正原有笔误:
<html> <body> <div class="card" id="search-card"> <div class="search"> <!-- 补全搜索框id,和JS选择器对应 --> <input type="text" name="searchbox" id="searcher" class="search-bar" placeholder="Search..."> <button id="searchBtn">🔍</button> </div> <div class="weather"> <h2 class="city">Weather in Accra</h2> <div class="temp"> <h1>21°C</h1> </div> <div class="flex"> <img src="" alt="" class="icon"> <div class="description">Cloudy</div> </div> <div class="humidity">Humid: 53% </div> <div class="wind"> Wind Speed: 6.2 km/h</div> </div> <h4>搜索历史</h4> <ul id="historyList"></ul> </div> </body> </html>
修正后的JavaScript代码
统一逻辑、补全交互、修复存储问题:
let weather = { apiKey: "", // 填入你自己的OpenWeatherMap接口密钥即可正常请求 fetchWeather: function(city) { fetch("https://api.openweathermap.org/data/2.5/weather?q="+ city + "&units=metric&appid="+ this.apiKey) .then((response) => { if(!response.ok) throw new Error("城市不存在或请求失败"); return response.json(); }) .then((data)=> { this.displayWeather(data); // 搜索成功后自动存入历史 this.saveToHistory(city.trim()); }) .catch(err => alert(err.message)); }, displayWeather: function(data){ const {name} = data; const {icon, description} = data.weather[0]; const {temp, humidity} =data.main; const {speed} = data.wind; document.querySelector(".city").innerText = "Weather in " + name; document.querySelector(".icon").src = "http://openweathermap.org/img/wn/"+ icon + ".png"; document.querySelector(".description").innerText = description; document.querySelector(".temp").innerText = temp+ "°C" ; document.querySelector(".humidity").innerText = "Humidity " + humidity + "%"; document.querySelector(".wind").innerText = "Wind Speed " + speed + "km/h"; }, search:function(){ const cityVal = document.querySelector(".search-bar").value.trim(); if(!cityVal) return; this.fetchWeather(cityVal); }, // 统一存储历史方法,做去重、条数限制 saveToHistory: function(city) { // 先移除已存在的同名城市,避免重复 saved = saved.filter(item => item.toLowerCase() !== city.toLowerCase()); // 最新搜索的记录放在最顶部 saved.unshift(city); // 最多保留10条历史,超出则删除最早的记录 if(saved.length > 10) saved.pop(); // 统一使用historyList作为键名存储 localStorage.setItem("historyList", JSON.stringify(saved)); // 重新渲染历史列表 renderHistoryList(); } } // 绑定搜索触发事件 document.querySelector("#searchBtn").addEventListener("click", () => weather.search()); document.querySelector(".search-bar").addEventListener("keydown", (e) => { if(e.key === "Enter") weather.search(); }) // 历史功能相关DOM const historyList = document.getElementById("historyList"); const searcher = document.getElementById("searcher"); // 初始化读取本地存储,做空值兼容 let saved = localStorage.getItem("historyList") ? JSON.parse(localStorage.getItem("historyList")) : []; // 统一渲染历史列表,避免重复代码 const renderHistoryList = () => { historyList.innerHTML = ""; saved.forEach((cityName) => { const li = document.createElement("li"); li.style.cssText = "display:flex;justify-content:space-between;align-items:center;margin:8px 0;padding:6px 10px;border-radius:4px;cursor:pointer;background:#f0f0f0;"; // 城市名点击直接查询对应天气 const cityText = document.createElement("span"); cityText.innerText = cityName; cityText.addEventListener("click", () => { searcher.value = cityName; weather.search(); }) // 单条删除按钮 const delBtn = document.createElement("button"); delBtn.innerText = "×"; delBtn.style.cssText = "border:none;background:transparent;cursor:pointer;font-size:18px;"; delBtn.addEventListener("click", (e) => { e.stopPropagation(); // 避免点击删除时触发城市查询 deleteHistory(delBtn); }) li.append(cityText, delBtn); historyList.appendChild(li); }) } // 修正删除逻辑的键名错误 const deleteHistory = (btn) => { const el = btn.parentNode; const index = [...el.parentElement.children].indexOf(el); saved.splice(index, 1); localStorage.setItem("historyList", JSON.stringify(saved)); renderHistoryList(); }; // 页面加载完成后自动渲染已有历史记录 window.addEventListener("load", renderHistoryList);
实现效果
- 搜索城市成功后自动保存记录,相同城市自动去重,最多保留10条最近搜索,最新记录置顶
- 点击历史条目里的城市名,直接触发该城市的天气查询
- 每条历史附带删除按钮,可单独删除对应记录,刷新页面数据不丢失
- 支持回车键触发搜索,空输入不会发起无效请求
- 所有本地存储操作统一使用
historyList作为键名,不会出现数据不匹配问题
内容的提问来源于stack exchange,提问作者KwameDickson
相关产品推荐
相关产品推荐

