2025年夏季《移动软件开发》实验报告

姓名:於佳杰 学号:23020007151
姓名和学号 於佳杰,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 准备
  1. API 密钥申请:访问和风天气开发者平台,注册账号。登录后进入 “控制台→我的服务”,获取个人专属 API 密钥,该密钥将用于后续网络请求的身份验证。
    在这里插入图片描述

  2. API 接口了解:了解api接口的用法,本次实验使用两个核心接口:

  • 地理编码接口(geo/v2/city/lookup):根据省市区名称获取唯一locationID(避免同名城市混淆);
    在这里插入图片描述

  • 实时天气接口(v7/weather/now):根据locationID获取温度、湿度、风向等实时天气数据。
    在这里插入图片描述

2.1.2 服务器域名配置

小程序要求所有网络请求的域名必须添加到 “合法域名白名单”,步骤如下:

  1. 登录微信公众平台,进入 “开发→开发设置→服务器域名”;

  2. 在 “request 合法域名” 栏点击 “修改”,添加和风天气 API 域名;

  3. 保存配置并重启微信开发者工具,确保域名配置生效(每月仅可修改 5 次,需谨慎操作)。
    在这里插入图片描述

在这里插入图片描述

2.1.2 天气图片下载
  1. 资源下载:下载天气图标素材,将图标文件存放于后续创建的images文件夹中,SVG 格式支持矢量缩放,适配所有设备分辨率,方便后续使用.
  2. 在这里插入图片描述

2.2 项目初始化:创建与基础配置

2.2.1 新建小程序项目
  1. 打开微信开发者工具,点击 “+ 新小程序项目”,在配置窗口中填写以下信息:
  • 项目名称:自定义为 “天气查询小程序”(仅用于工具管理,不影响用户端显示);

  • 目录:选择本地空文件夹(如D:\WeChatMiniProgram\WeatherDemo),路径需无中文和特殊字符;

  • AppID:粘贴 2.1.1 中获取的个人 AppID(或选择 “测试号”);

  • 开发模式:选择 “不使用云服务”,点击 “新建” 完成项目创建。
    在这里插入图片描述

2.2.2 冗余文件清理

为简化项目结构,删除无关文件,放置天气图片:

  1. 删除utils文件夹及其内部所有文件(工具类函数,本次实验无需使用);

  2. 删除pages文件夹下的logs目录及其内部所有文件(日志页面,与实验功能无关);

  3. 删除app.wxss中的默认样式(避免干扰自定义布局),后续样式通过页面级wxss定义。

  4. 新增images文件夹,并把下载的天气图片放到里面
    在这里插入图片描述

2.2.3 全局配置文件(app.json

app.json是小程序的全局配置文件,控制页面路径、窗口样式等核心参数,修改步骤如下:

  1. 页面路径配置:默认pages数组包含["pages/index/index", "pages/logs/logs"],删除"pages/logs/logs"及上一行末尾的逗号,仅保留首页路径("pages/index/index"),确保小程序启动时默认加载index页面;

  2. 窗口样式配置:添加window属性,统一所有页面的导航栏风格,代码逻辑如下:

  • "navigationBarBackgroundColor": "#3883EA":将导航栏背景色设为蓝色(与后续页面文本颜色呼应,保持色调统一);

  • "navigationBarTitleText": "今日天气":设置导航栏标题,明确小程序功能;

  • "navigationBarTextStyle": "white":将导航栏文字设为白色,与蓝色背景形成对比,提升可读性。

在这里插入图片描述

​ app.json完整代码展示

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">

&#x20; \<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)固定拼接,避免数据含义模糊。
    在这里插入图片描述

​ index.wxml完整代码展示
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; /*  内边距,避免元素贴边 */


}
  • 设计目的:通过100vhspace-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 项数据,且 “标题 - 数据” 对应清晰,避免信息混乱。
    在这里插入图片描述
​ index.wxss完整代码展示
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函数)
  • 功能:处理用户选择地区后的逻辑,更新地区数据并触发天气查询;

  • 实现步骤

  1. 获取选中的地区:通过e.detail.value获取用户选择的省市区数组(如["江苏省","南京市","玄武区"]);

  2. 更新地区数据:调用this.setData({region: e.detail.value}),更新data中的region变量,此时wxml中的{{region}}会自动刷新文本;

  3. 触发地理编码:调用this.getLocationID()(后续定义的地理编码函数),并通过then()链式调用this.getWeather(),确保 “地理编码完成→天气查询” 的顺序(避免异步请求导致的时序问题);

  • 代码逻辑
regionChange(e) {
  /* 更新选中的地区 */
  this.setData({
    region: e.detail.value
  });
  /* 先获取新地区的locationID,再查询天气 */
  this.getLocationID().then(() => {
    this.getWeather();
  });
}
3. 地理编码函数(getLocationID函数)
  • 功能:将用户选择的 “省市区” 转换为和风天气 API 所需的locationID(避免同名城市混淆);

  • 实现步骤

  1. 包装异步请求:用Promise包装wx.request(小程序网络请求接口),解决异步时序问题;

  2. 配置请求参数

  • url:地理编码接口地址;

  • data:包含location(城市名,如 “青岛”)、adm(省份名,如 “山东”)、key(API 密钥),adm参数用于过滤同名城市;

  1. 解析返回数据:请求成功后,从res.data.location[0].id中获取locationID,调用this.setData更新data中的locationID

  2. 通知请求完成:调用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 获取实时天气数据,并更新页面视图;

  • 实现步骤

  1. 保存this指向:定义const that = this,避免wx.request回调中this指向变更;

  2. 配置请求参数

  • url:实时天气接口地址;

  • data:包含locationlocationID)、key(API 密钥),确保接口识别查询目标;

  1. 解析返回数据:请求成功后,从res.data.HeWeather6[0].now中获取实时天气数据(如温度、湿度);

  2. 更新页面数据:调用that.setData({now: res.data.HeWeather6[0].now}),将获取的天气数据赋值给data中的now对象,小程序会自动更新wxml中所有绑定now属性的视图;

  3. 调试日志:添加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.js完整代码展示

在这里插入图片描述

​ index.js完整代码展示

在这里插入图片描述

​ index.js完整代码展示

三、程序运行结果

  1. 点击微信开发者工具顶部的 “编译” 按钮,模拟器会加载index页面,初始显示 “山东省青岛市黄岛区” 的天气数据;
    在这里插入图片描述

  2. 点击地区选择器,滚动选择其他地区如江苏省南京市玄武区,观察:

  • 地区文本更新为 “江苏省,南京市,玄武区”;

  • 控制台打印新的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 组件等的用法,让我对小程序的了解更加深入了一步,希望我能越学越好。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐