APP开发-Vue3+Vant实现不同地区动态获取天气信息功能

Posted L_不觉晓晓

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了APP开发-Vue3+Vant实现不同地区动态获取天气信息功能相关的知识,希望对你有一定的参考价值。

一、需求分析:

1、在APP首页有一个需求,要求根据不同地区显示当前地区的紫外线、温度、湿度、空气质量等。并且可以切换城市。
2、功能效果如下动图

二、技术分析

1、实现此功能主要有以下两个方面,首先我们要获取一个省市区列表,在我们使用的前端组件Vant里面已经提供了相关组件,我们直接使用即可。还有就是天气的接口,经过调查各个主流平台提供的天气查询接口,像高德是免费提供查询的,但是没有紫外线和空气质量的数据,还有其他平台不是提供查询数据不够,就是要收费的,经过对比还是决定使用百度地图提供的天气查询的API接口,它有免费和收费两种版本,免费的可以查询温度和湿度数据,紫外线和空气质量就是收费版提供的了。我们这里就先使用免费版的了,毕竟经费有限。
百度地图开放平台: https://lbsyun.baidu.com/index.php?title=webapi/weather#service-page-anchor-1-1
Vant官网: https://vant-contrib.gitee.io/vant/v3/#/zh-CN/area

三、功能实现

1、我们首先先把省市区列表实现出来,因为我们是弹出的一个popup框,所以,我们就需要把van-area组件放在里面,默认弹框是false,当点击事件触发变为true,在显示popup框。具体操作可参考组件文档,介绍的很详细。
html代码:

<!-- 地区选择 -->
  <van-popup v-model:show="showArea">
    <van-area
      :area-list="areaList1"
      @confirm="onAreaConfirm"
      @cancel="showArea = false"
      :value="cityId"
    />
 </van-popup>

2、获取天气信息
我们要调用查询天气API首先要申请一个百度开发者账号,具体流程可参考官网,然后根据官网提供的接口进行跨域请求,我们首先要配置一下跨区请求的地址,在vue.config.js里面进行如下配置,

module.exports = 
  publicPath: './',
  devServer: 
    proxy: 
      '/weather/': 
        target: 'http://api.map.baidu.com',
        ws: true, 
        changeOrigin: true, 
      ,
    ,
  ,
;

在自己创建的resource.js里面进行如下配置,

export default 
  weather:  url: `http://api.map.baidu.com/weather/v1/`, method: 'get' , // 天气信息取得API
;

配置完了就可以调用API:

  setup() 
    const  proxy  = getCurrentInstance();
    const weather = () => 
      // 获取天气信息
      proxy.$api.weather(
        district_id: state.cityId, // 城市code
        data_type: 'all',
        ak: BAI_DU_KEY, // 百度开发ak
      ).then((result) => 
        if (result.data.status === 0) 
          const dataList = result.data.result;
          // 地区名称
          state.weather.location = `$dataList.location.city $dataList.location.name`;
          // 温度区间
          state.weather.text_day = `$dataList.forecasts[0].text_day`;
          // 温度区间
          state.weather.weather = `$dataList.forecasts[0].low/$dataList.forecasts[0].high℃`;
          // 温度
          state.weather.temperature = dataList.now.temp;
          // 湿度
          state.weather.humidity = dataList.now.rh;
          // todo 护理建议接口
          state.weather.ultravioletRays = '5';
          state.weather.air = '32';
          if (proxy.$store.state.user.userId === '') 
            state.weather.advice = '注册用户后进行肤质测试,获取个性护肤建议';
           else 
            state.weather.advice = '温度较低相对干燥,经皮水分散失增加。可多次间隔使用保湿产品。室内建议使用加湿器。';
          
        
      );
    ;

完整代码如下:

<template>
  <div class="nursing-box">
    <!--护理建议-->
    <header class="nursing-header sub-title">
      <div class="sub-left">护理建议</div>
      <div @click="showArea = true" class="city-box">
        <van-icon size="20" name="location-o" />
        <div>weather.location ? weather.location.split(" ")[0] : ''</div>
      </div>
    </header>
    <!-- 天气建议 -->
    <div class="nursing">
      <div class="nursing-body">
        <div class="location">
          <div class="location-img">
            <img :src="require('@/assets/img/home/weather/weather.png')">
          </div>
          <div class="location-weather">
            <span>weather.weather</span>
            <div class="primary-info-list">weather.location</div>
          </div>
        </div>
        <div class="nursing-content">
          <div class="wether-info">
            <div class="wether-info-img">
              <img :src="require('@/assets/img/home/weather/ultravioletRays.png')">
            </div>
            <div class="wether-info-txt">
              <span>紫外线</span>
            </div>
            <div class="wether-info-txt-content">
              <span>weather.ultravioletRays</span>
            </div>
            <div class="wether-info-type">
              <div
                class="primary-info-list primary"
                v-if="weather.ultravioletRays < 2"
              >
                <span>最弱</span>
              </div>
              <div
                class="primary-info-list info"
                v-if="weather.ultravioletRays < 4 && weather.ultravioletRays > 2"
              >
                <span>较低</span>
              </div>
              <div
                class="primary-info-list warning"
                v-if="weather.ultravioletRays < 6 && weather.ultravioletRays > 4"
              >
                <span>中等</span>
              </div>
              <div
                class="primary-info-list danger"
                v-if=" weather.ultravioletRays > 6"
              >
                <span>最强</span>
              </div>
            </div>
          </div>
          <div class="wether-info">
            <div class="wether-info-img">
              <img :src="require('@/assets/img/home/weather/humidity.png')">
            </div>
            <div class="wether-info-txt">
              <span>湿度</span>
            </div>
            <div class="wether-info-txt-content">
              <span>weather.humidity%</span>
            </div>
            <div class="wether-info-type">
              <div
                class="primary-info-list warning"
                v-if="weather.humidity < 33"
              >
                <span>干燥</span>
              </div>
              <div
                class="primary-info-list primary"
                v-if="weather.humidity < 67 && weather.humidity >= 33"
              >
                <span>中等</span>
              </div>
              <div
                class="primary-info-list warning" v-if=" weather.humidity >= 67"
              >
                <span>潮湿</span>
              </div>
            </div>
          </div>
          <div class="wether-info">
            <div class="wether-info-img">
              <img :src="require('@/assets/img/home/weather/temperature.png')">
            </div>
            <div class="wether-info-txt">
              <span>温度</span>
            </div>
            <div class="wether-info-txt-content">
              <span>weather.temperature</span>
            </div>
            <div class="wether-info-type">
              <div
                class="primary-info-list primary"
                v-if="weather.temperature < 12 && weather.temperature >= -5"
              >
                <span>凉爽</span>
              </div>
              <div
                class="primary-info-list primary"
                v-if="weather.temperature < 18 && weather.temperature >= 12"
              >
                <span>温暖</span>
              </div>
              <div
                class="primary-info-list warning"
                v-if="weather.temperature < 30 && weather.temperature >= 18"
              >
                <span>&nbsp;&nbsp;&nbsp;&nbsp;</span>
              </div>
              <div
                class="primary-info-list danger"
                v-if=" weather.temperature >= 30"
              >
                <span>炎热</span>
              </div>
              <div
                class="primary-info-list danger"
                v-if=" weather.temperature < -5"
              >
                <span>寒冷</span>
              </div>
            </div>
          </div>
          <div class="wether-info">
            <div class="wether-info-img">
              <img :src="require('@/assets/img/home/weather/air.png')">
            </div>
            <div class="wether-info-txt">
              <span>空气</span>
            </div>
            <div class="wether-info-txt-content">
              <span>weather.air</span>
            </div>
            <div class="wether-info-type">
              <div class="primary-info-list primary" v-if="weather.air < 50">
                <span>&nbsp;&nbsp;&nbsp;&nbsp;</span>
              </div>
              <div class="primary-info-list info" v-if="weather.air < 100 && weather.air >=50">
                <span>&nbsp;&nbsp;&nbsp;&nbsp;</span>
              </div>
              <div
                class="primary-info-list warning"
                v-if="weather.air < 200 && weather.air >= 100"
              >
                <span>轻度污染</span>
              </div>
              <div class="primary-info-list danger" v-if="weather.air >=200">
                <span>严重污染</span>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div class="nursing-advice">
        <span class="nursing-body-left">建议</span>
        <span class="nursing-body-right">weather.advice</span>
      </div>
    </div>
    <!-- 地区选择 -->
    <van-popup v-model:show="showArea" style="width: 90%">
      <van-area
        :area-list="areaList1"
        @confirm="onAreaConfirm"
        @cancel="showArea = false"
        :value="cityId"
      />
    </van-popup>
  </div>
</template>

<script>
import 
  reactive, toRefs, onMounted, getCurrentInstance,
 from 'vue';
import  areaList  from '@/common/js/arealist';
import  BAI_DU_KEY  from '@/config';

export default 
  setup() 
    const  proxy  = getCurrentInstance();
    const state = reactive(
      cityId: '110101', // 城市code
      showArea: false,
      areaList1: areaList, // 城市list
      weather: , // 天气查询信息
    );

    const weather = () => 
      // 获取天气信息
      proxy.$api.weather(
        district_id: state.cityId, // 城市code
        data_type: 'all',
        ak: BAI_DU_KEY, // 百度开发ak
      ).then((result) => 
        if (result.data.status === 0) 
          const dataList = result.data.result;
          // 地区名称
          state.weather.location = `$dataList.location.city $dataList.location.name`;
          // 温度区间
          state.weather.text_day = `$dataList.forecasts[0].text_day`;
          // 温度区间
          state.weather.weather = `$dataList.forecasts[0].low/$dataList.forecasts[0].high℃`;
          // 温度
          state.weather.temperature = dataList.now.temp;
          // 湿度
          state.weather.humidity = dataList.now.rh;
          // todo 护理建议接口
          state.weather.ultravioletRays = '5';
          state.weather.air = '32';
          if (proxy.$store.state.user.userId === '') 
            state.weather.advice = '注册用户后进行肤质测试,获取个性护肤建议';
           else 
            state.weather.advice = '温度较低相对干燥,经皮水分散失增加。可多次间隔使用保湿产品。室内建议使用加湿器。';
          
        
      );
    ;

    // 地区选择器的动作
    const onAreaConfirm = (value) => 
      state.showArea = false;
      state.cityId = value[2].code;
      window.localStorage.setItem('city', state.cityId);
      // 调用天气API
      weather();
    ;

    onMounted(() => 
      const cityIdStorage = window.localStorage.getItem('city');
      if (cityIdStorage) 
        state.cityId = cityIdStorage;
       else 
        state.cityId = '110101';
      
      // 天气API
      weather();
    );

    return 
      ...toRefs(stateAPP开发-Vue3+Vant实现不同地区动态获取天气信息功能

App开发-使用Vue3+Vant组件实现历史搜索记录功能

使用Vue3+Vant组件实现App历史搜索记录功能

APP开发-Vue3+vant实现数据列表下拉分页功能

APP开发-Vue3+Vant+Html5+ 实现管理应用缓存以及清除缓存

APP开发-Vue3+Vant+Html5+ 实现管理应用缓存以及清除缓存