【愚公系列】《循序渐进Vue.js 3.x前端开发实践》054-案例:天气预报应用

举报
愚公搬代码 发表于 2025/03/30 17:27:47 2025/03/30
【摘要】 标题详情作者简介愚公搬代码头衔华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,CSDN商业化专家,阿里云专家博主,阿里云签约作者,腾讯云优秀博主,腾讯云内容共创官,掘金优秀博主,亚马逊技领云博主,51CTO博客专家等。近期荣誉2022年度博客之星TOP2,2023年度博客之星TOP2,2022年华为云十佳博主,2023年华为云十佳博主,2024年华为云十佳...
标题 详情
作者简介 愚公搬代码
头衔 华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,CSDN商业化专家,阿里云专家博主,阿里云签约作者,腾讯云优秀博主,腾讯云内容共创官,掘金优秀博主,亚马逊技领云博主,51CTO博客专家等。
近期荣誉 2022年度博客之星TOP2,2023年度博客之星TOP2,2022年华为云十佳博主,2023年华为云十佳博主,2024年华为云十佳博主等。
博客内容 .NET、Java、Python、Go、Node、前端、IOS、Android、鸿蒙、Linux、物联网、网络安全、大数据、人工智能、U3D游戏、小程序等相关领域知识。
欢迎 👍点赞、✍评论、⭐收藏

🚀前言

随着科技的快速发展和移动互联网的普及,天气预报应用成为了日常生活中不可或缺的一部分。无论是计划出行、安排户外活动,还是关注气候变化,准确的天气信息都能帮助我们做出更明智的决策。在这个背景下,我们将通过一个具体的案例,深入探讨如何开发一款功能丰富、用户友好的天气预报应用。

🚀一、案例:天气预报应用

🔎1.main.js

// 模块引入
import { createApp } from 'vue'
import App from './App.vue'
import VueAxios from 'vue-axios'
import axios from 'axios';
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
const app = createApp(App)
// 注册Element Plus图标组件
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
    // 向应用实例中全局注册图标组件
    app.component(key, component)
}
// 注册Element
app.use(ElementPlus)
// 注册axios
app.use(VueAxios, axios)
app.mount('#app')

这段 Vue 代码是一个典型的 Vue 3 项目初始化过程,主要做了以下几件事:模块引入、插件注册和应用挂载。接下来,我将逐步解释每行代码的作用:

🦋1.1 模块引入

import { createApp } from 'vue'
import App from './App.vue'
import VueAxios from 'vue-axios'
import axios from 'axios'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
  • import { createApp } from 'vue': 从 Vue 库中导入 createApp 方法,这是 Vue 3 创建应用实例的入口。
  • import App from './App.vue': 导入主组件 App.vue,这个组件是整个应用的根组件。
  • import VueAxios from 'vue-axios': 导入 vue-axios,它是 axios 的 Vue 插件,可以方便地在 Vue 组件中使用 axios 发起网络请求。
  • import axios from 'axios': 导入 axios,用于发送 HTTP 请求,通常用于与后端 API 进行交互。
  • import ElementPlus from 'element-plus': 导入 Element Plus UI 组件库,它是一个基于 Vue 3 的组件库,用于快速构建现代化的 Web 界面。
  • import 'element-plus/dist/index.css': 导入 Element Plus 的 CSS 样式文件,使得 UI 组件能正确显示。
  • import * as ElementPlusIconsVue from '@element-plus/icons-vue': 导入 Element Plus 提供的图标库,允许在项目中使用 Element Plus 的图标组件。

🦋1.2 创建 Vue 应用实例

const app = createApp(App)
  • createApp(App):通过 createApp 方法创建 Vue 应用实例,并将根组件 App 传递给它。这个 app 是后续对 Vue 应用进行配置和挂载的关键对象。

🦋1.3 全局注册 Element Plus 图标组件

for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
    // 向应用实例中全局注册图标组件
    app.component(key, component)
}
  • Object.entries(ElementPlusIconsVue):这个语句将 ElementPlusIconsVue 对象的每个键值对转化为数组形式(键是图标的名字,值是图标组件本身)。
  • for (const [key, component] of Object.entries(ElementPlusIconsVue)):通过 for...of 循环遍历所有的图标组件。
  • app.component(key, component):将每个图标组件注册为全局组件,这样在项目中的任何地方都可以使用这些图标,避免每次使用时都要单独导入。

🦋1.4 注册 Element Plus 插件

app.use(ElementPlus)
  • app.use(ElementPlus):将 Element Plus 作为插件注册到 Vue 应用中。这使得你可以在整个项目中使用 Element Plus 提供的 UI 组件和功能(如表格、按钮、弹窗等)。

🦋1.5 注册 axios 和 vue-axios 插件

app.use(VueAxios, axios)
  • app.use(VueAxios, axios):将 axiosvue-axios 插件注册到 Vue 应用中。这样,axios 实例将被注入到 Vue 的应用实例中,使得可以在任何组件中通过 this.axiosthis.$axios 来访问和发送 HTTP 请求。

🦋1.6 挂载 Vue 应用

app.mount('#app')
  • app.mount('#app'):将 Vue 应用实例挂载到页面上 ID 为 app 的 DOM 元素中。这个步骤意味着 Vue 会控制并渲染该 DOM 元素中的内容,并将根组件 App 作为渲染的入口。

🦋1.7 总结

这段代码完成了以下几个任务:

  1. 创建了 Vue 应用实例。
  2. 注册了 Element Plus 的图标组件,让它们可以在整个应用中全局使用。
  3. 安装了 Element Plus 组件库,使得应用能够使用 Element Plus 提供的 UI 组件。
  4. 注册了 axiosvue-axios,使得在 Vue 中能够方便地进行 HTTP 请求。
  5. 最后,将应用挂载到 #app DOM 元素上,启动 Vue 应用。

这段代码简洁而高效,通常是 Vue 项目初始化时的标准配置。

🔎2.App.vue

<script setup>
import WeatherDemo from './components/WeatherDemo.vue'
</script>

<template>
  <WeatherDemo/>
</template>

<style scoped>
.logo {
  height: 6em;
  padding: 1.5em;
  will-change: filter;
  transition: filter 300ms;
}
.logo:hover {
  filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
  filter: drop-shadow(0 0 2em #42b883aa);
}
</style>

这段代码就不做说明

🔎3.WeatherDemo.vue

<script setup>
import { onMounted, getCurrentInstance, ref, watch} from 'vue'

const city = ref("上海")
const weatherData = ref({})
const todayData = ref({})
const plc = ref("暂无数据")
const realtime = ref({})
const futureData = ref([])
const requestData = () => {
    let c = encodeURI(city.value)
    let api = `/simpleWeather/query?city=${c}&key=key`
    axios.get(api).then((response)=>{
        weatherData.value = response.data
        todayData.value = weatherData.value.result.future[0]
        realtime.value = weatherData.value.result.realtime
        futureData.value = weatherData.value.result.future
        console.log(response.data)
    })
}
let axios = getCurrentInstance().appContext.app.axios

// 组件挂载时,进行默认数据的初始化
onMounted(() => {
    axios.defaults.baseURL = '/myApi'
    requestData()
}) 

 // 当用户输入的城市发生变化后,调用接口进行数据请求
watch(city, ()=>{
    requestData()
})
</script>

<template>
    <el-container class="container">
        <el-header>
            <el-input placeholder="请输入" class="input" v-model="city">
                <template #prepend>城市名:</template>
            </el-input>
        </el-header>
        <el-main class="main">
            <div class="today">
                今天:
                <span>{{todayData.weather ?? plc}} {{todayData.temperature ?? plc}}</span>
                <span style="margin-left:20px">{{todayData.direct ?? plc}}</span>
                <span style="margin-left:100px">{{todayData.date}}</span>
            </div>
            <div class="real">
                <span class="temp">{{realtime.temperature ?? plc}}°</span>
                <span class="realInfo">{{realtime.info ?? plc}}</span>
                <span class="realInfo" style="margin-left:20px">{{realtime.direct ?? plc}}</span>
                <span class="realInfo" style="margin-left:20px">{{realtime.power ?? plc}}</span>
            </div>
            <div class="real">
                <span class="realInfo">空气质量:{{realtime.aqi ?? plc}}°</span>
                <span class="realInfo" style="margin-left:20px">湿度:{{realtime.humidity ?? plc}}</span>
            </div>
            <div class="future">
                <div class="header">5日天气预报</div>
                <el-table :data="futureData" style="margin-top:30px">
                    <el-table-column prop="date" label="日期"></el-table-column>
                    <el-table-column prop="temperature" label="温度"></el-table-column>
                    <el-table-column prop="weather" label="天气"></el-table-column>
                    <el-table-column prop="direct" label="风向"></el-table-column>
                </el-table>
            </div>
        </el-main>
    </el-container>
</template>

<style>
.container {
    background: linear-gradient(rgb(13, 104, 188), rgb(54, 131, 195));
}
.input {
    width: 300px;
    margin-top: 20px;
}
.today {
    font-size: 20px;
    color: white;
}
.temp {
    font-size: 79px;
    color: white;
}
.realInfo {
    color: white;
}
.future {
    margin-top: 40px;
}
.header {
    color: white;
    font-size: 27px;
}
</style>

在这里插入图片描述

🦋3.1 <script setup> 部分

这是 Vue 3 中一种新的书写方式,<script setup> 提供了更简洁的 API 使用方法。

☀️3.1.1 导入 Vue 的 API

import { onMounted, getCurrentInstance, ref, watch } from 'vue'
  • onMounted:生命周期钩子,当组件挂载完成后执行。
  • getCurrentInstance:获取当前组件实例,通常用于访问 Vue 的内部实例。
  • ref:用于创建响应式引用,用于存储和追踪数据。
  • watch:用来观察数据的变化,并在数据变化时执行某些操作。

☀️3.1.2 定义响应式数据

const city = ref("上海")              // 当前城市
const weatherData = ref({})            // 天气数据
const todayData = ref({})              // 今天的天气数据
const plc = ref("暂无数据")            // 默认显示文本
const realtime = ref({})               // 实时天气数据
const futureData = ref([])             // 未来天气数据
  • city:当前选中的城市(默认为“上海”)。
  • weatherData:保存从 API 获取的完整天气数据。
  • todayData:保存当天的天气数据。
  • plc:如果数据缺失时显示的默认文本(“暂无数据”)。
  • realtime:保存当前实时天气数据。
  • futureData:保存未来天气的数据。

☀️3.1.3 请求数据函数

const requestData = () => {
    let c = encodeURI(city.value) // 将城市名称进行 URI 编码
    let api = `/simpleWeather/query?city=${c}&key=b801ab8d9ef23d37e8ff394083a4728e`
    axios.get(api).then((response) => {
        weatherData.value = response.data
        todayData.value = weatherData.value.result.future[0]  // 今天的数据
        realtime.value = weatherData.value.result.realtime  // 实时数据
        futureData.value = weatherData.value.result.future  // 未来几天的数据
        console.log(response.data)
    })
}
  • requestData:此函数会根据当前 city 发起 HTTP GET 请求,获取天气数据。
  • 请求的 API 地址为 /simpleWeather/query,带有 city(城市)和 key(API 密钥)参数。
  • 数据请求成功后,更新 weatherDatatodayDatarealtimefutureData 等响应式数据。

☀️3.1.4 获取 Axios 实例

let axios = getCurrentInstance().appContext.app.axios
  • getCurrentInstance():获取当前组件的实例,appContext.app.axios 用来访问全局注册的 axios 实例。

☀️3.1.5 组件挂载时初始化

onMounted(() => {
    axios.defaults.baseURL = '/myApi'  // 设置 axios 的基础 URL
    requestData()  // 调用 requestData 函数,获取默认城市的数据
})
  • onMounted():当组件挂载时,设置 axiosbaseURL/myApi,然后调用 requestData 函数请求天气数据。

☀️3.1.6 城市变化时重新请求数据

watch(city, () => {
    requestData()  // 当用户输入的城市发生变化时,重新请求数据
})
  • watch(city, ...):当 city(城市)发生变化时,触发 requestData 函数,重新获取对应城市的天气数据。

🦋3.2 <template> 部分

这是 Vue 组件的模板部分,用于描述组件的视图结构。

☀️3.2.1 UI 结构

<el-container class="container">
    <el-header>
        <el-input placeholder="请输入" class="input" v-model="city">
            <template #prepend>城市名:</template>
        </el-input>
    </el-header>
    <el-main class="main">
        <div class="today">
            今天:
            <span>{{ todayData.weather ?? plc }} {{ todayData.temperature ?? plc }}</span>
            <span style="margin-left:20px">{{ todayData.direct ?? plc }}</span>
            <span style="margin-left:100px">{{ todayData.date }}</span>
        </div>
        <div class="real">
            <span class="temp">{{ realtime.temperature ?? plc }}°</span>
            <span class="realInfo">{{ realtime.info ?? plc }}</span>
            <span class="realInfo" style="margin-left:20px">{{ realtime.direct ?? plc }}</span>
            <span class="realInfo" style="margin-left:20px">{{ realtime.power ?? plc }}</span>
        </div>
        <div class="real">
            <span class="realInfo">空气质量:{{ realtime.aqi ?? plc }}°</span>
            <span class="realInfo" style="margin-left:20px">湿度:{{ realtime.humidity ?? plc }}</span>
        </div>
        <div class="future">
            <div class="header">5日天气预报</div>
            <el-table :data="futureData" style="margin-top:30px">
                <el-table-column prop="date" label="日期"></el-table-column>
                <el-table-column prop="temperature" label="温度"></el-table-column>
                <el-table-column prop="weather" label="天气"></el-table-column>
                <el-table-column prop="direct" label="风向"></el-table-column>
            </el-table>
        </div>
    </el-main>
</el-container>
  • el-container:Element Plus 提供的布局容器,用于分隔页面的不同部分。
  • el-input:输入框组件,v-model="city" 实现了双向数据绑定,当用户输入城市名时,city 会自动更新。
  • el-table:用于展示未来 5 天的天气预报数据。
  • {{ }}:插值表达式,用于显示 todayDatarealtimefutureData 中的天气信息。如果某个数据为空,则显示默认文本 plc(“暂无数据”)。

☀️3.2.2 显示天气信息

  • 显示今天的天气,包括 weathertemperature(温度)、direct(风向)和 date(日期)。
  • 显示实时天气数据:温度、天气信息、风向、风力等。
  • 显示空气质量(aqi)和湿度(humidity)。
  • 显示 5 天的天气预报:日期、温度、天气和风向。

🦋3.3 <style> 部分

.container {
    background: linear-gradient(rgb(13, 104, 188), rgb(54, 131, 195));
}
.input {
    width: 300px;
    margin-top: 20px;
}
.today {
    font-size: 20px;
    color: white;
}
.temp {
    font-size: 79px;
    color: white;
}
.realInfo {
    color: white;
}
.future {
    margin-top: 40px;
}
.header {
    color: white;
    font-size: 27px;
}
  • container:为整个容器设置背景色,使用渐变色。
  • input:设置输入框的宽度和顶部边距。
  • todaytemprealInfo 等:设置文本的字体大小和颜色(大部分为白色)。
  • future:设置未来天气预报部分的顶部边距。
  • header:设置未来天气预报标题的颜色和字体大小。

🦋3.4 总结

这段代码实现了一个简单的天气应用,允许用户输入城市名,获取该城市的天气数据并展示。它利用了 Vue 3 的 Composition API 来组织组件的逻辑,并使用 Element Plus 组件库来构建 UI。关键功能包括:

  • 获取天气数据并展示当天、实时和未来几天的天气。
  • 使用 watch 监听城市变化,自动更新天气数据。
  • 使用 axios 发送 API 请求并处理返回的数据。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。