用 Vue3 + 高德地图 API 构建实时天气展示系统

2,604 阅读3分钟

一、项目概述

本教程将基于 Vue3 框架与高德地图 API,实现一个包含实时时间、地理位置自动识别的天气看板系统。效果包含:

  • 实时显示本地时间(每秒更新)
  • 自动定位当前所在城市
  • 天气信息可视化展示(温度/风力/湿度等)

效果图

动画.gif

二、核心代码解析

1. 模板结构(语义化布局)

html

复制

<template>
  <div class="container">
    <!-- 导航栏:时间 + 城市切换 -->
    <nav class="nav">
      <div class="time">{{ localTime }}</div>
      <div class="city">切换城市</div>
    </nav>
    
    <!-- 天气信息主体 -->
    <main class="city-info">
      <div class="city-name">{{ weatherData.city }}</div>
      <div class="weather">{{ weatherData.weather }}</div>
      <h2 class="temp"><em>{{ weatherData.temperature }}</em></h2>
      <div class="detail">
        <span>风力:{{ weatherData.windPower }}</span>
        <span>风向:{{ weatherData.windDirection }}</span>
        <span>湿度:{{ weatherData.humidity }}</span>
      </div>
    </main>
  </div>
</template>

运行 HTML

2. 脚本逻辑(组合式API)

javascript

复制

<script setup>
import { ref, onMounted } from "vue";
import AMapLoader from "@amap/amap-jsapi-loader";

// 响应式数据
const localTime = ref("00:00");
const weatherData = ref({
  city: "北京",
  weather: "晴",
  temperature: "20",
  windPower: "3级",
  windDirection: "东北",
  humidity: "80%"
});

// 初始化地图定位
const initMap = () => {
  AMapLoader.load({
    key: '你的高德Key', // 需替换为真实Key
    version: '2.0',
    plugins: ['AMap.CitySearch']
  }).then((AMap) => {
    AMap.plugin('AMap.CitySearch', function() {
      const citySearch = new AMap.CitySearch();
      citySearch.getLocalCity((status, result) => {
        if (status === 'complete' && result.info === 'OK') {
          weatherData.value.city = result.city.replace('市', ''); // 更新城市名
        }
      });
    });
  });
};

// 生命周期钩子
onMounted(() => {
  initMap();
  setInterval(() => {
    localTime.value = new Date().toLocaleTimeString(); // 每秒更新时间
  }, 1000);
});
</script>

3. 样式设计(Scoped样式)

css

复制

<style scoped>
.container {
  min-height: 100vh;
  background: rgba(0,0,0,0.6);
  color: #fff;
}
.nav {
  padding: 10px;
  display: flex;
  justify-content: space-between;
}
.city-info {
  text-align: center;
  margin-top: 2rem;
}
.temp em {
  font-size: 4rem;
  font-style: normal;
}
</style>

三、高德地图 API 接入指南

1. 前期准备

  1. 前往高德开放平台注册账号
  2. 进入「应用管理」→ 创建新应用 → 获取 Key
  3. 在「安全设置」中添加域名白名单(本地开发可填 localhost

2. 重要配置

在 index.html 中添加安全协议(解决本地调用问题):

html

复制

<!-- 放在 head 标签内 -->
<script type="text/javascript">
  window._AMapSecurityConfig = {
    securityJsCode: '你的安全密钥', // 高德后台获取
  };
</script>

运行 HTML

3. API 核心方法

javascript

复制

AMapLoader.load({
  key: 'YOUR_KEY',
  version: '2.0',
  plugins: ['AMap.CitySearch'] // 按需加载插件
}).then((AMap) => {
  // 初始化地图相关操作
});

四、功能扩展建议

  1. 接入真实天气数据

    • 使用高德天气查询API
    • 根据获取的城市名称请求天气详情
  2. 增加城市切换功能

    javascript

    复制

    const changeCity = (cityName) => {
      // 调用天气API获取新城市数据
    }
    
  3. 添加加载状态

    javascript

    复制

    const isLoading = ref(true);
    // API请求完成后设置为false
    

五、注意事项

  1. Key 安全保护

    • 切勿将 Key 直接暴露在前端代码中(生产环境应通过后端转发)
    • 严格设置安全密钥(_AMapSecurityConfig
  2. 错误处理优化

    javascript

    复制

    citySearch.getLocalCity((status, result) => {
      if (status === 'error') {
        console.error('定位失败:', result.info);
      }
    });
    
  3. 样式兼容性

    • 使用 flex 布局替代 float
    • 添加响应式设计(媒体查询

六、源码自取,顺便添加了切换城市功能

<template>
    <div class="container">
        <!-- 导航 -->
        <!-- html5 语义化标签 -->
        <nav class="nav">
            <div class="time">{{ localTime }}</div>
            <div class="city">
                <input v-model="cityName" placeholder="输入城市名称" />
                <button @click="changeCity">切换城市</button>
            </div>
        </nav>
        <main class="city-info">
            <div class="city-name">{{ weatherData.city }}</div>
            <div class="weather">{{ weatherData.weather }}</div>
            <h2 class="temp">
                <em>{{ weatherData.temperature }}</em>
            </h2>
            <div class="detail">
                <span>风力: {{ weatherData.windPower }}</span>
                <span>风向: {{ weatherData.windDirection }}</span>
                <span>湿度: {{ weatherData.humdity }}</span>
            </div>
        </main>
        <!-- 天气 -->
    </div>
</template>

<script setup>
import { ref, onMounted } from "vue";
import AMapLoader from "@amap/amap-jsapi-loader";

const localTime = ref("00:00");
const weatherData = ref({
    city: "北京",
    weather: "晴",
    temperature: "20",
    windPower: "3级",
    windDirection: "东北",
    humdity: "80%"
});
const cityName = ref("");

const init_map = () => {
    AMapLoader.load({
        key: '5b0756265d33f9c1d9926a51fc1bfdcc',
        version: '2.0',
        plugins: ['AMap.CitySearch']
    }).then((AMap) => {
        AMap.plugin('AMap.CitySearch', function () {
            let citySearch = new AMap.CitySearch();
            citySearch.getLocalCity(function (status, result) {
                if (status === 'complete' && result.info === 'OK') {
                    console.log(result.city);
                    weatherData.value.city = result.city;
                    // 调用获取天气信息的函数
                    getWeather(result.city);
                }
            });
        });
    });
};

const getWeather = (city) => {
    // 使用高德地图的天气查询服务获取天气信息
    AMapLoader.load({
        key: '5b0756265d33f9c1d9926a51fc1bfdcc',
        version: '2.0',
        plugins: ['AMap.Weather']
    }).then((AMap) => {
        let weather = new AMap.Weather();
        weather.getLive(city, function (err, data) {
            if (!err) {
                weatherData.value = {
                    city: data.city,
                    weather: data.weather,
                    temperature: data.temperature,
                    windPower: data.windPower,
                    windDirection: data.windDirection,
                    humdity: data.humidity
                };
            }
        });
    });
};

const changeCity = () => {
    if (cityName.value) {
        getWeather(cityName.value);
    }
};

// 当组件挂载完成后执行
onMounted(() => {
    init_map();
    setInterval(() => {
        localTime.value = new Date().toLocaleTimeString();
    }, 1000);
});
</script>

<style scoped>
.container {
    min-height: 100vh;
    background-color: black;
    opacity: 0.6;
    color: #fff;
}
.nav {
    overflow: auto;
    padding: 10px;
}
.city {
    float: right;
}
.time {
    float: left;
}
.city-info {
    text-align: center;
}
.tmperature {
    font-size: 26px;
}
.tmperature em {
    font-size: px;
}
</style>