《移动软件开发》 小程序网络API:天气查询

使用小程序网络API 的相关应用制作一款天气查询小程序。

一、实验目标

1、掌握服务器域名配置和临时服务器部署;2、掌握 wx.request 接口的用法。

二、实验步骤

列出实验的关键步骤、代码解析、截图。

注意:

本实验来自于周文洁老师的《微信小程序开发实战》第五章。主要介绍使用小程序
网络API 的相关应用制作一款天气查询小程序。
 
注意事项: 
1、本实验中,需要使用和风天气API,需要注册用户,大家请自行阅读和风天气官
方文档:https://dev.qweather.com/docs/api/weather/weather-now/ 
2、实验中需要的天气图片、utils.js 下载地址为:
https://gaopursuit.oss-cn-beijing.aliyuncs.com/2022/demo2_file.zip 
3、因为要向和风天气发送请求,如果保持登录状态将无法发送请求,切换为游客模式即可。

1.1 准备工作

1.1.1 API 密钥申请

介绍如何申请获得开源API的密钥。(以下内容使用和风天气API,网址为‘https://www.heweather.com/’)

1.1.1.1 注册账号

1.1.1.2 获取API密钥

点击左上角的“三” → “项目管理”

项目名称:任意

选择订阅:免费订阅

设置KEY:适用平台:Web API

key名称:任意

接下开就会获得密钥KEY(点击蓝色的查看即可获得密钥)

1.1.2 地区ID的获取

我们后面需要将地区的名称转化为ID方便查询,原因后面会揭晓

使用网址:https://geoapi.qweather.com(暂时忽略)

1.1.3 服务器域名配置

小程序与指定域名地址进行网络通信需要将该域名添加至白名单

1.1.3.1 登录 mp.weixin.qq.com

左侧导航栏中 “管理” → “开发管理”

下翻至服务器域名

点击修改,扫码身份验证后进入配置服务器域名

填写

https://devapi.qweather.com;https://geoapi.qweather.com;

注意

(1)可能网页会在最后自动补充“;”

(2)第一个网址是我们查询天气的API网址,第二个网址是将地址名称转化为地址ID的网址

1.2 项目创建

填写名称、目录、选择AppID,选择不使用云服务,模板选择JS基础模板

1.3 页面配置

1.3.1 创建页面文件

(1)将app.json中pages属性中的“pages/logs/logs"删除

1.3.2 删除和修改文件

(1)删除utils文件夹及其内部所有内容

(2)删除pages文件夹下的logs目录及其内部所有内容

(3)删除index.wxml和index.wxss中的所有代码

(4)删除index.js中的所有代码,并且输入关键词”page“找到第二个选项按回车键让其自动补全函数

(5)删除app.wxss中的所有代码

(6)删除app.js中的全部代码,并且输入关键词”app“找到第二个选项按回车键让其自动补全函数

1.3.3 创建其他文件

(1)下载天气图标

https://gaopursuit.oss-cn-beijing.aliyuncs.com/2022/demo2_file.zip

(2)直接解压到项目文件夹中(如我这里就是“2222”项目文件夹)

(解压后有三个文件夹都包含全套图标,选择一套喜欢的图标后要将其余两个删除,不然会文件过大报错)

(3)在文件操作系统中将第二级目录,即图标(.png)的父目录更名为 weather_icon

部分目录结构如下:

1.4 视图设计

1.4.1 导航栏设计

更改导航栏背景颜色和标题

修改文件:app.json

标题:今日天气

背景:#3883FA (蓝色)

app.json 代码:

{
  "pages": [
    "pages/index/index"
  ],
  "window": {
    "navigationBarTitleText": "今日天气",
    "navigationBarBackgroundColor": "#3883FA"
  }
}

预览效果:

1.4.2 页面设计

页面包括页面整体和四个主要区域

  • 页面整体:<view>组件,并定义class='container';

  • 区域1:地区选择器,选择查询的省、市、区 <picker>

  • 区域2:显示查询城市的温度和天气状态 <text>

  • 区域3:显示查询城市的天气图标 <image>

  • 区域4:分行显示其他天气信息,比如湿度、气压、风向等

    区域4内单元行:4个<view>组件,代表四行 。定义class='bar'

    区域4内单元格:每行3个<view>组件,代表有3列。定义class='box'

1.4.2.1 整体容器设计

pages/index/index.wxml 定义页面容器 <view>

<view class='container'>
</view>

app.wxss 中设置容器样式(布局)

.container{
  height: 100vh;          
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-around;
}

目前只有单独的主页,并没有组件元素,还看不出来flex布局模型效果

1.4.2.2 区域1(地区选择器)设计

pages/index/index.wxml 使用<picker>组件实现地区选择器(目前默认为北京市)

<view class='container'>
  <!--区域 1:地区选择器-->
  <picker mode='region'>
    <view>北京市</view>
  </picker>
</view>
1.4.2.3 区域2(文本)设计

pages/index/index.wxml 使用<text>组件显示当前城市温度和天气状况

<view class='container'>
  <!--区域 1:地区选择器-->
  <picker mode='region'>
    <view>北京市</view>
  </picker>
  <!--区域 2:单行天气信息-->
  <text>19℃晴</text>
</view>

pages/index/index.wxss 中设计文本样式

text{
  font-size: 80rpx;
  color:#3C5F81;
}
1.4.2.4 区域3(天气图标)设计

pages/index/index.wxml 使用<image>组件展示图标

<view class='container'>
  <!--区域 1:地区选择器-->
  <picker mode='region'>
    <view>北京市</view>
  </picker>
  <!--区域 2:单行天气信息-->
  <text>19℃晴</text>
  <!--区域 3:天气图标-->
  <image src='/images/weather_icon/999.png' mode="widthFix"></image>
</view>

pages/index/index.wxss 中设计图标样式

image{
  width: 220rpx;
}
1.4.2.5 区域4(多行其他天气信息)设计

pages/index/index.wxml 使用<image>组件展示图标

<view class='container'>
  <!--区域 1:地区选择器-->
  <picker mode='region'>
    <view>北京市</view>
  </picker>
  <!--区域 2:单行天气信息-->
  <text>19℃晴</text>
  <!--区域 3:天气图标-->
  <image src='/images/weather_icon/999.png' mode="widthFix"></image>
  <!--区域4:多行天气信息-->
  <view class='detail'>
    <view class='bar'>
      <view class='box'>温度</view>
      <view class='box'>气压</view>
      <view class='box'>能见度</view>
    </view>
    <view class='bar'>
      <view class='box'>0 %</view>
      <view class='box'>0 hpa</view>
      <view class='box'>0 km</view>
    </view>
    <view class='bar'>
      <view class='box'>风向</view>
      <view class='box'>风速</view>
      <view class='box'>风力</view>
    </view>
    <view class='bar'>
      <view class='box'>0 </view>
      <view class='box'>0 km/h</view>
      <view class='box'>0 级</view>
    </view>
  </view> 
</view>

pages/index/index.wxss 中设计图标样式

.detail{
  width: 100%;
  display: flex;
  flex-direction: column;
}
.bar{
  display: flex;
  flex-direction: row;
  margin: 20rpx 0;
}
.box{
  width: 33.3%;
  text-align: center;
}

效果图:

1.5 逻辑实现

1.5.1 更新省、市、区信息

(1)显示选择地区,添加自定义bindchange事件监听选项变化

pages/index/index.wxml

添加 bindchange='regionChange'

将 “北京市” 改为 “{{region}}”

  <!--区域 1:地区选择器-->
  <picker mode='region'bindchange='regionChange'>
    <view>{{region}}</view>
  </picker>

(2)初始化region,region是一个含三个项目的数组

pages/index/index.js

Page({
  /**
   * 页面的初始数据
   */
  data: {
    region:['安徽省','芜湖市','镜湖区'],
  },
  
  regionChange: function(e) {
    this.setData({region: e.detail.value});
    this.getWeather();
  },
})

效果图:

1.5.2 获取实况天气数据

pages/index/index.js 中自定义getWeather获取实况天气数据

Page({
  getWeather: function() {
    var that = this;
    // 第一步:获取 location ID
    wx.request({
      url: "https://geoapi.qweather.com/v2/city/lookup",//将地区名称转化为地区ID
      data: {
        location: that.data.region[2],  //精确到区
        key: '和风天气密钥' //注意替换为之前申请的key
      },
      success: function(res) {
        if (res.data && res.data.code === "200" && res.data.location.length > 0) {
          var locationId = res.data.location[0].id;  // 获取第一个结果的 location ID
          
          // 第二步:使用 location ID 获取天气信息
          wx.request({
            url: "https://devapi.qweather.com/v7/weather/now",
            data: {
              location: locationId,  // 使用获取到的 location ID
              key: '和风天气密钥' //注意替换为之前申请的key
            },
            success: function(res) {
              console.log(res.data);  // 打印天气信息
            }
          });
        } else {
          console.error("Location ID not found");
        }
      }
    });
  },
})
//更新天气
  regionChange: function(e) {
    this.setData({region: e.detail.value});
    this.getWeather();
  },
  
  onLoad: function (options) {
    this.getWeather();
  },

编译后在Console控制台得到返回数据(格式如下图,重点在于有now中的天气信息)

pages/index/index.js

将上面中的打印返回信息 变为 更新显示的天气信息

Page({
  getWeather: function() {
    ...
      success: function(res) {
        if (res.data && res.data.code === "200" && res.data.location.length > 0) {
          ...
          wx.request({
            ...
            success: function(res) {
              that.setData({now:res.data.now})  //修改此处
            }
          });
        }
        ...
        }
      }
    });
  },
})
​

1.5.3 更新页面天气信息

pages/index/index.wxml 将所有默认数据替换为返回结果now中对应数据

<view class='container'>
  <!--区域 1:地区选择器-->
  <picker mode='region'bindchange='regionChange'>
    <view>{{region}}</view>
  </picker>
  <!--区域 2:单行天气信息-->
  <text>{{now.temp}}℃{{now.text}}</text>
  <!--区域 3:天气图标-->
  <image src='/images/weather_icon/{{now.icon}}.png' mode="widthFix"></image>
  <!--区域4:多行天气信息-->
  <view class='detail'>
    <view class='bar'>
      <view class='box'>温度</view>
      <view class='box'>气压</view>
      <view class='box'>能见度</view>
    </view>
    <view class='bar'>
      <view class='box'>{{now.humidity}} %</view>
      <view class='box'>{{now.pressure}} hpa</view>
      <view class='box'>{{now.vis}} km</view>
    </view>
    <view class='bar'>
      <view class='box'>风向</view>
      <view class='box'>风速</view>
      <view class='box'>风力</view>
    </view>
    <view class='bar'>
      <view class='box'>{{now.windDir}} </view>
      <view class='box'>{{now.windSpeed}} km/h</view>
      <view class='box'>{{now.windScale}} 级</view>
    </view>
  </view>
</view>

pages/index/index.js 设置now的默认值(初始值),在网速受限的条件下临时先显示这些默认值

部分代码:

  data: {
    region:['安徽省','芜湖市','镜湖区'],
    now:{
      temp:0,
      text:'未知',
      icon:'999',
      humidity:0,
      pressure:0,
      vis:0,
      windDir:0,
      windSpeed:0,
      windScale:0
    }
  },
​

1.6 目录结构及完整代码

目录结构

pages/index/index.js

Page({
  getWeather: function() {
    var that = this;
    // 第一步:获取 location ID
    wx.request({
      url: "https://geoapi.qweather.com/v2/city/lookup",
      data: {
        location: that.data.region[2],  
        key: '45625ad6a77c44c7a2d99977de9aef41'
      },
      success: function(res) {
        if (res.data && res.data.code === "200" && res.data.location.length > 0) {
          var locationId = res.data.location[0].id;  // 获取第一个结果的 location ID
          
          // 第二步:使用 location ID 获取天气信息
          wx.request({
            url: "https://devapi.qweather.com/v7/weather/now",
            data: {
              location: locationId,  // 使用获取到的 location ID
              key: '45625ad6a77c44c7a2d99977de9aef41'
            },
            success: function(res) {
              console.log(res.data);  // 打印天气信息
              that.setData({now:res.data.now})
            }
          });
        } else {
          console.error("Location ID not found");
        }
      }
    });
  },
  /**
   * 页面的初始数据
   */
  data: {
    region:['安徽省','芜湖市','镜湖区'],
    now:{
      temp:0,
      text:'未知',
      icon:'999',
      humidity:0,
      pressure:0,
      vis:0,
      windDir:0,
      windSpeed:0,
      windScale:0
    }
  },
​
  regionChange: function(e) {
    this.setData({region: e.detail.value});
    this.getWeather();
  },
  
  onLoad: function (options) {
    this.getWeather();
  },
})
​

pages/index/index.wxml

<view class='container'>
  <!--区域 1:地区选择器-->
  <picker mode='region'bindchange='regionChange'>
    <view>{{region}}</view>
  </picker>
  <!--区域 2:单行天气信息-->
  <text>{{now.temp}}℃{{now.text}}</text>
  <!--区域 3:天气图标-->
  <image src='/images/weather_icon/{{now.icon}}.png' mode="widthFix"></image>
  <!--区域4:多行天气信息-->
  <view class='detail'>
    <view class='bar'>
      <view class='box'>温度</view>
      <view class='box'>气压</view>
      <view class='box'>能见度</view>
    </view>
    <view class='bar'>
      <view class='box'>{{now.humidity}} %</view>
      <view class='box'>{{now.pressure}} hpa</view>
      <view class='box'>{{now.vis}} km</view>
    </view>
    <view class='bar'>
      <view class='box'>风向</view>
      <view class='box'>风速</view>
      <view class='box'>风力</view>
    </view>
    <view class='bar'>
      <view class='box'>{{now.windDir}} </view>
      <view class='box'>{{now.windSpeed}} km/h</view>
      <view class='box'>{{now.windScale}} 级</view>
    </view>
  </view>
</view>

pages/index/index.wxss

text{
  font-size: 80rpx;
  color:#3C5F81;
}
image{
  width: 220rpx;
}
.detail{
  width: 100%;
  display: flex;
  flex-direction: column;
}
.bar{
  display: flex;
  flex-direction: row;
  margin: 20rpx 0;
}
.box{
  width: 33.3%;
  text-align: center;
}
​

app.json

{
  "pages": [
    "pages/index/index"
  ],
  "window": {
    "navigationBarTitleText": "今日天气",
    "navigationBarBackgroundColor": "#3883FA"
  },
  "style": "v2",
  "componentFramework": "glass-easel",
  "sitemapLocation": "sitemap.json",
  "lazyCodeLoading": "requiredComponents"
}

app.wxss

.container{
  height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-around;
}

三、程序运行结果

列出程序的最终运行结果及截图。

默认界面:

选择界面:                                                 查询结构界面:

四、问题总结与体会

1. 实验过程中遇到的问题

在实验过程中,我遇到了以下问题:

  • 和风天气API的使用问题:由于实验需要使用和风天气API获取天气数据,初次使用时对于API的调用方法不熟悉,尤其是在如何传递正确的参数和解析返回数据上遇到了困难。

  • 微信小程序域名配置问题:配置服务器域名时,遇到域名验证失败的问题。经过查找资料,发现是由于域名未通过HTTPS验证,导致微信小程序不接受请求。

  • 页面更新的逻辑实现:在编写获取天气数据并更新页面显示的代码时,遇到了异步请求数据的处理问题,导致页面刷新不及时。

2. 问题的解决方法
  • 学习API文档:仔细阅读和风天气API的官方文档,理解API的使用方法和参数的意义。通过调试工具逐步验证传入参数的正确性,最终成功获取并解析天气数据。

  • 域名配置问题的解决:通过将临时服务器切换至支持HTTPS的域名,完成了域名的配置,并成功与微信小程序对接。

  • 页面更新问题的解决:通过将异步请求的回调函数与页面刷新逻辑结合,确保在数据获取成功后立即更新页面,保证了用户体验的流畅性。

3. 收获与体会
  • API调用的经验:通过本次实验,我对如何使用第三方API获取数据有了更深入的理解,特别是在处理异步请求和数据解析方面,积累了宝贵的经验。

  • 微信小程序开发技巧:通过这个实验,熟悉了微信小程序开发的基本流程,包括项目创建、页面配置、视图设计以及逻辑实现,为后续的开发奠定了基础。

4. 对课程安排的建议

建议在课程中增加更多关于常见问题的解决方案讨论,如API调用中的常见错误、异步数据处理技巧等,这样能够帮助学生更好地应对实际开发中的挑战。此外,可以增加实验报告的交流环节,让学生分享他们在实验中的心得体会和遇到的困难,共同提高开发技能。

  • 27
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值