如何在异步函数中实现数据与视图分离——天气应用模块拆分需求
解决方案:数据与视图分离重构
1. 重构weather.js:专注数据获取
把原函数里的DOM操作、输入读取逻辑全部移除,让这个模块只负责从API拉取并返回天气数据,成为纯数据处理层:
// weather.js async function getWeatherData(location) { try { const baseURL = "https://api.openweathermap.org/data/2.5/weather?units=imperial&appid=02dbfb3b0a9eca931937cb67ff5eba51&q="; const response = await fetch(`${baseURL}${location}`, { mode: "cors" }); const data = await response.json(); // 提前整理视图需要的数据结构,减少视图层的处理成本 return { country: data.sys.country, city: data.name, temp: data.main.temp, humidity: data.main.humidity, description: data.weather[0].description }; } catch (error) { console.error(error); return null; // 用null标记数据获取失败 } }
2. 新建dom.js:专注视图渲染
这个模块负责所有DOM相关操作,包括读取用户输入、渲染天气数据、显示错误提示:
// dom.js // 提前缓存DOM元素,避免重复查询 const searchInput = document.getElementById("search"); const weatherContainer = document.createElement("div"); document.body.appendChild(weatherContainer); // 渲染天气数据的核心函数 function renderWeather(data) { if (!data) { weatherContainer.textContent = "Location not found, please try again."; return; } // 用清晰的格式拼接内容,替代原有的JSON字符串替换操作 const weatherContent = ` ${data.country}, ${data.city} Temperature: ${data.temp}°F Humidity: ${data.humidity}% Weather: ${data.description} `.trim(); weatherContainer.textContent = weatherContent; } // 获取用户输入的封装函数 function getSearchLocation() { return searchInput.value.trim(); }
3. 主入口文件:连接数据层与视图层
在主脚本(比如app.js)里,通过事件绑定串联两个模块的功能:
// app.js import { getWeatherData } from './weather.js'; import { getSearchLocation, renderWeather } from './dom.js'; // 绑定搜索按钮的点击事件(假设你有id为search-btn的按钮) document.getElementById("search-btn").addEventListener("click", async () => { const location = getSearchLocation(); if (!location) return; // 空输入直接跳过 const weatherData = await getWeatherData(location); renderWeather(weatherData); });
核心逻辑说明
- 打破函数作用域限制:通过将数据作为函数返回值传递,再传入视图层的渲染函数,实现跨模块的数据共享。
- 职责拆分:weather.js只处理数据获取和整理,dom.js只负责DOM操作,代码耦合度极低,后续修改维护更方便。
- 避免跨层操作:数据层完全不接触DOM,视图层只负责把数据转换成页面内容,符合前端分层开发的最佳实践。
内容的提问来源于stack exchange,提问作者DataMoshing
相关产品推荐
相关产品推荐

