2025年夏季《移动软件开发》实验报告—实验2:天气查询小程序
2025年夏季《移动软件开发》实验报告
姓名和学号 | 於佳杰,23020007151 |
---|---|
本实验属于哪门课程? | 中国海洋大学25夏《移动软件开发》 |
实验名称 | 天气查询小程序 |
博客地址 | https://blog.csdn.net/2303_80449862/article/details/150780579?spm=1001.2014.3001.5501 |
Github仓库地址 | https://github.com/KeepingMoving/2025_Mobile-software-development/tree/main |
(备注:将实验报告发布在博客、代码公开至 github 是 加分项,不是必须做的)
一、实验目标
1、掌握微信小程序的基础开发流程,包括项目创建、页面配置、文件结构梳理等核心环节
2、熟练使用小程序常用组件(如picker、text、image、view),深入理解各组件的功能定位、使用场景及参数配置逻辑,能根据需求选择合适的组件实现交互效果。
3、掌握 Flex 布局在小程序样式设计中的应用,能通过flex-direction、justify-content、align-items等属性实现合理的页面排版,提升页面美观度和适配性。
4.掌握wx.request接口的使用,能发起网络请求调用第三方 API,处理异步请求逻辑,并解析返回的 JSON 数据。
二、实验步骤
2.1 实验准备:环境与资源配置
在正式开发前,需完成API 密钥申请、服务器域名配置、以及天气图片下载等工作,确保后续开发流程顺畅。
2.1.1 和风天气 API 准备
-
API 密钥申请:访问和风天气开发者平台,注册账号。登录后进入 “控制台→我的服务”,获取个人专属 API 密钥,该密钥将用于后续网络请求的身份验证。
-
API 接口了解:了解api接口的用法,本次实验使用两个核心接口:
-
地理编码接口(
geo/v2/city/lookup
):根据省市区名称获取唯一locationID
(避免同名城市混淆); -
实时天气接口(
v7/weather/now
):根据locationID
获取温度、湿度、风向等实时天气数据。
2.1.2 服务器域名配置
小程序要求所有网络请求的域名必须添加到 “合法域名白名单”,步骤如下:
-
登录微信公众平台,进入 “开发→开发设置→服务器域名”;
-
在 “request 合法域名” 栏点击 “修改”,添加和风天气 API 域名;
-
保存配置并重启微信开发者工具,确保域名配置生效(每月仅可修改 5 次,需谨慎操作)。
2.1.2 天气图片下载
- 资源下载:下载天气图标素材,将图标文件存放于后续创建的
images
文件夹中,SVG 格式支持矢量缩放,适配所有设备分辨率,方便后续使用.
2.2 项目初始化:创建与基础配置
2.2.1 新建小程序项目
- 打开微信开发者工具,点击 “+ 新小程序项目”,在配置窗口中填写以下信息:
-
项目名称:自定义为 “天气查询小程序”(仅用于工具管理,不影响用户端显示);
-
目录:选择本地空文件夹(如
D:\WeChatMiniProgram\WeatherDemo
),路径需无中文和特殊字符; -
AppID:粘贴 2.1.1 中获取的个人 AppID(或选择 “测试号”);
-
开发模式:选择 “不使用云服务”,点击 “新建” 完成项目创建。
2.2.2 冗余文件清理
为简化项目结构,删除无关文件,放置天气图片:
-
删除
utils
文件夹及其内部所有文件(工具类函数,本次实验无需使用); -
删除
pages
文件夹下的logs
目录及其内部所有文件(日志页面,与实验功能无关); -
删除
app.wxss
中的默认样式(避免干扰自定义布局),后续样式通过页面级wxss
定义。 -
新增images文件夹,并把下载的天气图片放到里面
2.2.3 全局配置文件(app.json
)
app.json
是小程序的全局配置文件,控制页面路径、窗口样式等核心参数,修改步骤如下:
-
页面路径配置:默认
pages
数组包含["pages/index/index", "pages/logs/logs"]
,删除"pages/logs/logs"
及上一行末尾的逗号,仅保留首页路径("pages/index/index"
),确保小程序启动时默认加载index
页面; -
窗口样式配置:添加
window
属性,统一所有页面的导航栏风格,代码逻辑如下:
-
"navigationBarBackgroundColor": "#3883EA"
:将导航栏背景色设为蓝色(与后续页面文本颜色呼应,保持色调统一); -
"navigationBarTitleText": "今日天气"
:设置导航栏标题,明确小程序功能; -
"navigationBarTextStyle": "white"
:将导航栏文字设为白色,与蓝色背景形成对比,提升可读性。
2.3 页面文件开发:分文件详细实现
2.3.1 页面结构文件(index.wxml
)
index.wxml
定义页面的视图结构,采用 “分区域模块化” 设计,将页面划分为地区选择器、核心天气信息、天气图标、详细天气信息4 个区域,每个区域通过组件实现功能,代码逻辑与设计思路如下:
1. 整体容器(view.container
)
-
功能:作为页面的 “外层框架”,统一控制所有子元素的布局;
-
组件使用:用
view
组件包裹所有内容,添加class="container"
便于通过wxss
设置样式; -
设计逻辑:采用 Flex 布局实现垂直分布,确保各区域在不同屏幕尺寸下均匀排列,避免拥挤或空白。
2. 地区选择器(picker
组件)
-
功能:让用户选择目标地区,获取省市区数据用于后续天气查询;
-
组件原理:
picker
是小程序自带的滚动选择器,mode="region"
时自动加载微信内置的省市区数据,无需手动维护地区列表; -
代码逻辑与使用说明:
\<picker mode="region" bindchange="regionChange">
  \<view>{{region}}\</view>
\</picker>
-
mode="region"
:指定组件为 “省市区三级联动选择器”,用户可滚动选择省、市、区; -
bindchange="regionChange"
:绑定regionChange
事件,用户选择完成后,组件会通过该事件返回选中的省市区数组(比如我的["山东省","青岛市","黄岛区"]
); -
{{region}}
:动态绑定data
中的region
变量,初始显示默认地区,选择后实时更新文本,实现 “数据驱动视图”。
3. 核心天气信息(text
组件)
-
功能:突出展示温度和天气状态(如 “25℃晴”),是用户最关注的核心信息;
-
组件使用:用
text
组件承载文本,通过数据绑定动态更新内容,代码逻辑如下:
\<text>{{now.temp}}°C {{now.text}}\</text>
-
{{now.temp}}
:绑定now
对象的temp
属性(实时温度),单位 “℃” 固定拼接,确保数据可读性; -
{{now.text}}
:绑定now
对象的text
属性(天气状态,如 “晴”“多云”),与温度并列展示,让用户快速获取关键信息; -
设计逻辑:后续通过
wxss
设置大字体和深色,确保核心信息 “一眼可见”。
4. 天气图标(image
组件)
-
功能:通过可视化图标展示天气状态(如太阳图标代表晴天),比纯文字更直观;
-
组件使用:用
image
组件加载本地图标文件,代码逻辑如下:
\<image src="/images/{{now.icon}}.svg" mode="widthFix">\</image>
-
src="/images/{{now.icon}}.svg"
:src
属性指定图片路径,{{now.icon}}
绑定now
对象的icon
属性(和风天气 API 返回的天气代码,如 “100” 对应晴天),动态匹配images
文件夹中的 SVG 图标; -
mode="widthFix"
:设置图片缩放模式,宽度固定时高度按比例自适应,避免图标拉伸变形(SVG 格式确保缩放后无失真); -
前置操作:在项目根目录新建
images
文件夹,将下载的天气图标 SVG 文件放入,确保路径与src
一致。
5. 详细天气信息(view
组件嵌套)
-
功能:展示湿度、气压、能见度等 6 项详细数据,采用 “表格化布局” 确保信息清晰;
-
组件使用:通过
view
组件嵌套实现 “外层容器→行→列” 结构,代码逻辑如下: -
结构逻辑:
-
外层容器(
detail
):包裹所有详细信息,控制整体宽度和垂直排列; -
行容器(
bar
):每个bar
代表一行,水平排列 3 个 “列容器”,实现 “三列布局”; -
列容器(
box
):每个box
代表一列,占行宽的 1/3,承载标题或数据,确保排版整齐;
-
-
数据绑定:
{{now.humidity}}
(湿度)、{{now.pressure}}
(气压)等均绑定now
对象的属性,单位(如%
、hPa
)固定拼接,避免数据含义模糊。
2.3.2 页面样式文件(index.wxss
)
index.wxss
用于定义index.wxml
的样式,基于 Flex 布局实现页面排版,确保各区域美观且适配多设备,各样式类的设计逻辑如下:
1. 整体容器样式(.container
)
-
功能:控制页面所有子元素的垂直分布和对齐方式;
-
样式代码与逻辑:
.container {
height: 100vh; /* 容器高度占满整个视窗,避免滚动条 */
display: flex; /* 启用Flex布局 *\
flex-direction: column; /* 主轴为垂直方向,子元素从上到下排列 */
align-items: center; /* 子元素在水平方向(交叉轴)居中对齐 */
justify-content: space-around; /* 子元素在垂直方向均匀分布,间距相等 *\
padding: 20rpx; /* 内边距,避免元素贴边 */
}
- 设计目的:通过
100vh
和space-around
确保页面全屏显示且各区域间距均匀,提升用户体验。
2. 地区选择器样式(picker
与内部view
)
-
功能:让地区选择器文本清晰、点击区域明显;
-
样式代码与逻辑:
picker {
width: 80%; /* 选择器宽度占屏幕80%,避免过宽或过窄 */
text-align: center; /* 文本居中 */
}
picker view {
font-size: 32rpx; /* 字体大小,rpx为小程序自适应单位(1rpx≈0.5px) */
color: #3C5F81; /* 深蓝色文本,与导航栏呼应 */
padding: 15rpx 0; /* 上下内边距,扩大点击区域 */
border-bottom: 1px solid #E5E5E5; /* 底部边框,区分选择器与其他区域 */
}
3. 核心天气信息样式(text
)
-
功能:突出温度和天气状态,确保核心信息醒目;
-
样式代码与逻辑:
text {
font-size: 80rpx; /* 大字体,确保远距离可见 */
color: #3C5F81; /* 深蓝色文本,与整体色调统一 */
font-weight: 600; /* 字体加粗,增强视觉冲击力 */
margin: 30rpx 0; /* 上下外边距,与其他区域分隔 */
}
4. 天气图标样式(image
)
-
功能:控制图标大小,确保显示清晰且不占过多空间;
-
样式代码与逻辑:
image {
width: 220rpx; /* 图标宽度固定,适配多数屏幕 */
height: auto; /* 高度自动,配合`mode="widthFix"`避免变形 */
margin: 20rpx 0; /* 上下外边距,与核心信息、详细信息分隔 */
}
5. 详细天气信息样式(.detail
、.bar
、.box
)
-
功能:实现表格化布局,确保详细数据清晰有序;
-
样式代码与逻辑:
/* 外层容器:控制整体宽度和垂直排列 */
.detail {
width: 100%; /* 占满屏幕宽度,充分利用空间 */
display: flex;
flex-direction: column; /* 行容器垂直排列 */
margin-top: 20rpx;
}
/* 行容器:控制列容器水平排列 */
.bar {
display: flex;
flex-direction: row; /* 列容器水平排列 */
margin: 15rpx 0; /* 行与行之间的垂直间距 */
}
/* 列容器:控制文本对齐和宽度 */
.box {
width: 33.3%; /* 三列均分一行宽度 */
text-align: center; /* 文本居中,确保排版整齐 */
font-size: 28rpx; /* 字体大小适中,避免拥挤 */
color: #666; /* 深灰色文本,与核心信息区分优先级 */
}
- 设计目的:通过 “三列四行” 的表格化布局,在有限屏幕空间内展示 6 项数据,且 “标题 - 数据” 对应清晰,避免信息混乱。
2.3.3 页面逻辑文件(index.js
)
index.js
是页面的逻辑核心,负责数据初始化、事件处理、网络请求等,遵循 “数据驱动视图” 理念,通过setData
方法实现数据与视图的同步更新,各函数的实现步骤与逻辑如下:
1. 初始数据定义(data
对象)
在Page
构造函数中定义data
对象,设置页面初始数据,避免加载时空白,代码逻辑如下:
Page({
data: {
/* 地区选择初始值:省、市、区数组 */
region: ['山东省', '青岛市', '黄岛区'],
/* 地区ID(和风天气API所需参数,初始为青岛市ID) */
locationID: '101120201',
/* 实时天气数据对象,初始值避免页面空白 */
now: {
temp: 0, /* 温度 */
text: '未知', /* 天气状态 */
icon: '999', /* 天气图标代码(999对应“未知”图标) */
humidity: 0, /* 湿度 */
pressure: 0, /* 气压 */
vis: 0, /* 能见度 */
windDir: '未知',/* 风向 */
windSpeed: 0, /* 风速 */
windScale: 0 /* 风力 */
}
}
})
- 设计逻辑:初始数据选择 “山东省青岛市黄岛区”,因其为常见城市,数据查询成功率高;
now
对象的初始值(如temp: 0
)确保网络请求未完成时,页面显示占位数据,提升用户感知。
2. 地区选择事件(regionChange
函数)
-
功能:处理用户选择地区后的逻辑,更新地区数据并触发天气查询;
-
实现步骤:
-
获取选中的地区:通过
e.detail.value
获取用户选择的省市区数组(如["江苏省","南京市","玄武区"]
); -
更新地区数据:调用
this.setData({region: e.detail.value})
,更新data
中的region
变量,此时wxml
中的{{region}}
会自动刷新文本; -
触发地理编码:调用
this.getLocationID()
(后续定义的地理编码函数),并通过then()
链式调用this.getWeather()
,确保 “地理编码完成→天气查询” 的顺序(避免异步请求导致的时序问题);
- 代码逻辑:
regionChange(e) {
/* 更新选中的地区 */
this.setData({
region: e.detail.value
});
/* 先获取新地区的locationID,再查询天气 */
this.getLocationID().then(() => {
this.getWeather();
});
}
3. 地理编码函数(getLocationID
函数)
-
功能:将用户选择的 “省市区” 转换为和风天气 API 所需的
locationID
(避免同名城市混淆); -
实现步骤:
-
包装异步请求:用
Promise
包装wx.request
(小程序网络请求接口),解决异步时序问题; -
配置请求参数:
-
url
:地理编码接口地址; -
data
:包含location
(城市名,如 “青岛”)、adm
(省份名,如 “山东”)、key
(API 密钥),adm
参数用于过滤同名城市;
-
解析返回数据:请求成功后,从
res.data.location[0].id
中获取locationID
,调用this.setData
更新data
中的locationID
; -
通知请求完成:调用
resolve()
,告知regionChange
函数 “地理编码已完成”;
- 代码逻辑:
getLocationID() {
const that = this; /* 保存Page实例指向,避免回调中this指向变更 */
return new Promise((resolve) => {
wx.request({
url: 'https://free-api.heweather.com/s6/geo/city/lookup',
data: {
location: that.data.region[1], /* 选中的城市名(数组第2项) */
adm: that.data.region[0], /* 选中的省份名(数组第1项) */
key: '你的API密钥' /* 替换为个人申请的API密钥 */
},
success(res) {
/* 获取返回的locationID */
const locationID = res.data.HeWeather6[0].basic.cid;
/* 更新data中的locationID */
that.setData({
locationID: locationID
});
resolve(); /* 通知Promise完成 */
}
});
});
}
4. 天气数据获取函数(getWeather
函数)
-
功能:调用和风天气 API 获取实时天气数据,并更新页面视图;
-
实现步骤:
-
保存
this
指向:定义const that = this
,避免wx.request
回调中this
指向变更; -
配置请求参数:
-
url
:实时天气接口地址; -
data
:包含location
(locationID
)、key
(API 密钥),确保接口识别查询目标;
-
解析返回数据:请求成功后,从
res.data.HeWeather6[0].now
中获取实时天气数据(如温度、湿度); -
更新页面数据:调用
that.setData({now: res.data.HeWeather6[0].now})
,将获取的天气数据赋值给data
中的now
对象,小程序会自动更新wxml
中所有绑定now
属性的视图; -
调试日志:添加
console.log(res.data)
,在控制台打印返回数据,便于调试(如查看数据结构是否正确);
- 代码逻辑:
getWeather() {
const that = this;
wx.request({
url: 'https://free-api.heweather.com/s6/weather/now',
data: {
location: that.data.locationID, /* 已获取的locationID */
key: '你的API密钥' /* 替换为个人API密钥 */
},
success(res) {
/* 解析实时天气数据 */
const weatherData = res.data.HeWeather6[0].now;
/* 更新页面数据,视图自动刷新 */
that.setData({
now: weatherData
});
/* 打印数据用于调试 */
console.log('实时天气数据:', weatherData);
},
fail(err) {
/* 请求失败提示 */
wx.showToast({
title: '天气数据获取失败',
icon: 'none',
duration: 2000
});
console.error('请求错误:', err);
}
});
}
5. 页面加载生命周期函数(onLoad
)
-
功能:页面首次加载时触发,仅执行一次,用于初始化天气数据;
-
实现逻辑:调用
this.getWeather()
,直接使用初始locationID
(青岛市)查询天气,确保页面加载后快速显示数据,无需用户手动操作; -
代码逻辑:
onLoad(options) {
/* 页面加载时自动查询初始地区的天气 */
this.getWeather();
}
三、程序运行结果
-
点击微信开发者工具顶部的 “编译” 按钮,模拟器会加载
index
页面,初始显示 “山东省青岛市黄岛区” 的天气数据; -
点击地区选择器,滚动选择其他地区如江苏省南京市玄武区,观察:
-
地区文本更新为 “江苏省,南京市,玄武区”;
-
控制台打印新的
locationID
和天气数据; -
核心信息区(温度、天气状态)和详细信息区同步更新;
四、问题总结与体会
1.问题:图标路径缺少动态天气代码,加载失败,报错 Failed to load local image resource /images/weather_icon/.png,因路径未拼接天气代码,小程序找不到对应图标。
解决方法:在 WXML 中通过天气数据字段 {{weather.icon}} 动态拼接路径,确保路径为 /images/weather_icon/{{weather.icon}}.svg ,同时保证 JS 中 weather.icon 能正确获取天气代码,从接口返回数据赋值,设置默认值避免空值
2.问题:接口数据字段与代码逻辑不匹配,接口返回天气代码字段是 cond_code ,但代码中用 weather.icon 接收,导致 weather.icon 无值,路径拼接失败。
解决方法:核对天气 API 文档,确认返回字段名,调整代码赋值逻辑。
3.体会通过本次学习,开发里常用动态拼接让页面更灵活,但只要有一个环节掉链子比如数据没拿到、变量名写错,就全崩。这让我明白,写动态逻辑时,得 “从头到尾盯细节”—— 从接口返回啥数据、怎么存到 data 里,到 WXML 里怎么用变量,每一步都得和拼图一样严丝合缝。同时本次实验我也学习了picker 组件等的用法,让我对小程序的了解更加深入了一步,希望我能越学越好。
更多推荐
所有评论(0)