随着天气变得越来越不可预测,我们经常需要查看天气预报来规划我们的日常活动。那么,为什么不自己打造一个专属的天气预报员呢?今天,我们将使用Vue框架来创建一个简单但实用的天气预报应用。
1. 初始化Vue项目
首先,我们需要创建一个新的Vue项目。你可以使用Vue CLI或者Vite来初始化项目。在这个例子中,我们将使用Vue CLI。 打开终端,运行以下命令来创建一个新的Vue项目:
vue create weather-app
按照提示选择Vue版本和所需的配置选项。
2. 安装依赖
进入项目目录,安装所需的依赖项:
cd weather-app
npm install vue-router vant echarts @vant/area-data
这些依赖项包括:
vue-router
:Vue的路由管理器。vant
:有赞团队的一个轻量、可靠的移动端Vue组件库。echarts
:一个使用JavaScript实现的可视化库。@vant/area-data
:Vant UI库提供的地区数据。
3. 配置路由
在src
目录下创建一个名为router
的文件夹,并在其中创建一个名为index.js
的文件。这将是我们存放路由配置的地方。
// src/router/index.js
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes: [
{
path: '/',
name: 'Home',
component: () => import('../views/HomeView.vue')
}
]
})
export default router
在src
目录下创建一个名为views
的文件夹,并在其中创建一个名为Home.vue
的文件。这将是我们应用的首页。
<template>
<div class="home">
<h1>欢迎使用天气预报应用</h1>
</div>
</template>
<script>
export default {
name: 'HomeView'
}
</script>
4. 配置Vant UI库
在main.js
中,我们需要引入并使用Vant UI库。Vant UI 是一个基于 Vue.js 的高质量、轻量级的移动端 UI 组件库,由有赞前端团队开发并开源。Vant 的目标是为开发者提供一套开箱即用的组件集合,以加速移动应用的开发流程。它覆盖了一系列常见的移动端界面组件,比如导航、表单元素、按钮、列表、轮播图等,同时支持按需引入,有助于减少项目的体积。这是它的网址Vant UI
// src/main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import { Area, ActionSheet } from 'vant';
import 'vant/lib/index.css';
const app = createApp(App)
app.use(router)
app.use(Area);
app.use(ActionSheet)
app.mount('#app')
5. 创建天气预报页面
在views
文件夹中创建一个名为WeatherView.vue
的文件,这是我们的天气预报页面。
<!-- src/views/WeatherView.vue -->
<template>
<div class="weather">
<!-- ... -->
</div>
</template>
<script setup>
// ...
</script>
<style scoped>
/* ... */
</style>
6. 添加时间和城市切换功能
在WeatherView.vue
的模板部分,添加时间和城市切换的界面。
<template>
<div class="weather">
<div class="nav">
<div class="time">{{ now }}</div>
<div class="city" @click="state.show = true">切换城市</div>
</div>
<!-- ... -->
</div>
</template>
在脚本部分,添加时间和一些动态属性。
<script setup>
import { ref, reactive, onBeforeMount, onMounted, nextTick } from 'vue';
import * as echarts from 'echarts';
import { areaList } from '@vant/area-data';
let now = ref("00:00:00");
setInterval(() => {
now.value = new Date().toLocaleTimeString()
}, 1000)
const state = reactive({
city: "",
today: {},
show: false,
// ...
})
// ...
</script>
-
实时时间更新: 使用ref创建了一个名为now的响应式引用,初始化为"00:00:00"。 通过setInterval函数每秒调用一次匿名函数,该函数更新now引用的值为当前的本地时间字符串。这样,now的值会每秒自动更新,反映实时时间。
-
状态管理: 使用reactive创建了一个名为state的对象,该对象包含了多个响应式属性:
- city:用于存储当前选择的城市名。
- today:用于存储当前城市的天气信息。
- show:布尔值,用于控制城市选择器的显示与否。
7. 添加地区选择器
使用Vant的Area
组件来创建一个地区选择器。在使用之前,我们先要阅读一下快速上手,学会使用它。我已经导入好了包,在这里我就不带着大家去了解了,有需要的可以去看看官方文档
然后在左侧往下拉,找到业务组件,就可以看到area组件了
首先我们先要在全局(main.js)注册好组件
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import "./assets/reset.css"
import { Area } from 'vant';
import { ActionSheet } from 'vant';
const app = createApp(App)
app.use(router)
app.use(Area);
app.use(ActionSheet)
app.mount('#app')
再来到WeatherView.vue
<template>
<div class="weather">
<div class="nav">
<div class="time">{{ now }}</div>
<div class="city" @click="state.show = true">切换城市</div>
</div>
<!-- ... -->
<van-action-sheet v-model:show="state.show" title="地区">
<div class="content"><van-area v-model="value" :area-list="areaList" :columns-num="2" @confirm="selectCity"
@cancel="state.show = false" />
</div>
</van-action-sheet>
</div>
</template>
当 state里的show为true van-action-sheet
组件显示 为false 就消失
在脚本部分,添加地区选择器的逻辑。
<script setup>
import { ref } from 'vue';
import { Area } from 'vant';
import { areaList } from '@vant/area-data';
// ...
const selectCity = ({ selectedOptions }) => {
// console.log(selectedOptions[1].text);
state.city = selectedOptions[1].text
getWeather(selectedOptions[1].text)
state.show = false
}
// ...
</script>
代码解释:这是定义在area组件中的确定按钮,目的是点击确定后这个组件消失,并且把选择的城市传给state里的city,实现响应式更新
8. 获取天气数据
使用高德地图的API来获取实时天气和未来天气预报数据。这里也是利用了高德地图的定位以及天气的查询来实现的,可以到高德地图的官网高德开放平台注册账号去申请一个Api,选择,下图的js api
然后在左侧的准备中它会教你如何获取apiKey,看完准备后记得看一下快速上手,它会教你如何把高德地图的api导入你的项目之中
我们来到进阶教程,找到定位和天气
首先我们先获取到当前定位,对于一个天气app来说,肯定需要先获取当前定位的信息。 我们选择ip定位,把下面的代码复制下来
然后粘贴到组件中,然后把查询到的城市赋值给自己声明的变量中
AMap.plugin('AMap.CitySearch', function () {
var citySearch = new AMap.CitySearch()
citySearch.getLocalCity(function (status, result) {
if (status === 'complete' && result.info === 'OK') {
// 查询成功,result即为当前所在城市信息
state.city = result.city
getWeather(result.city)
}
})
})
因为获取天气是根据当前城市信息来获取的,而且在各种地方都需要使用到,所有我直接把它包装成了一个方法来复用
在获取天气的方法里,我用到了高德地图里天气的api
const getWeather = (city) => {
//加载天气查询插件
AMap.plugin("AMap.Weather", function () {
//创建天气查询实例
var weather = new AMap.Weather();
//执行实时天气信息查询
weather.getLive(city, function (err, data) {
console.log(err, data);
//err 正确时返回 null
//data 返回实时天气数据,返回数据见下表
state.today = data
});
});
}
到这里我们就已经获取到天气信息了
9. 显示天气信息
在模板部分,添加显示天气信息的界面。
<template>
<div class="weather">
<!-- ... -->
<div class="weather-info">
<p class="city">{{ weatherData.city }}</p>
<p class="temp">{{ weatherData.temp }}</p>
<p class="weather">{{ weatherData.weather }}</p>
</div>
</div>
</template>
在脚本部分,添加显示天气信息的逻辑。
<script setup>
import { ref } from 'vue';
import { Area } from 'vant';
import { areaList } from '@vant/area-data';
const weatherData = ref({
city: '',
temp: '',
weather: '',
});
const onCitySelected = (values) => {
const city = values[1].name;
// 调用获取天气的函数
getWeather(city);
showCitySelector.value = false;
};
// 使用高德地图的API来获取实时天气和未来天气预报数据
const getWeather = async (city) => {
// ...
// 更新weatherData
weatherData.value = {
city: data.city,
temp: data.temp,
weather: data.weather,
};
};
// ...
</script>
目前的天气情况我们就已经大致做完了,最后把天气预报加上就可以了
一样的,高德地图为我们提供了未来七天的天气预报API,我们只需要抄作业就行了
因为它的api跟获取当前天气信息是差不多的,所有我们也把他放在封装好的getWeather
函数里,我在状态栏里定义了一个future数组,这里我只截取展现了未来两天的天气情况,
const state = reactive({
city: "",
today: {},
show: false,
future: [],
data: []
})
const getWeather = (city) => {
//加载天气查询插件
AMap.plugin("AMap.Weather", function () {
//创建天气查询实例
var weather = new AMap.Weather();
//执行实时天气信息查询
weather.getLive(city, function (err, data) {
console.log(err, data);
//err 正确时返回 null
//data 返回实时天气数据,返回数据见下表
state.today = data
});
weather.getForecast(city, function (err, data) {
console.log(err, data);
//err 正确时返回 null
//data 返回天气预报数据,返回数据见下表
state.future = data.forecasts.slice(1, 3)
// console.log(state.future[0]);
state.data = data.forecasts
// initEcharts()
nextTick(() => {
initEcharts(data.forecasts.map(item => item.dayTemp))
})
});
});
}
渲染到页面中
<div class="future" v-if="state.future.length">
<div class="group">
明天:
<span class="tm">白天:{{ state.future[0].dayTemp }}℃ {{ state.future[0].dayWeather }}
{{ state.future[0].dayWindPower }}级</span>
<span class="tm">夜晚:{{ state.future[0].nightTemp }}℃ {{ state.future[0].nightWeather }}
{{ state.future[0].nightWindPower }}级</span>
</div>
<div class="group">
后天:
<span class="tm">白天:{{ state.future[1].dayTemp }}℃ {{ state.future[1].dayWeather }}
{{ state.future[1].dayWindPower }}级</span>
<span class="tm">夜晚:{{ state.future[1].nightTemp }}℃ {{ state.future[1].nightWeather }}
{{ state.future[1].nightWindPower }}级</span>
</div>
</div>
下面是完整的js代码
import { ref, reactive, onBeforeMount, onMounted, nextTick } from 'vue';
import * as echarts from 'echarts';
import { areaList } from '@vant/area-data';
let now = ref("00:00:00");
setInterval(() => {
now.value = new Date().toLocaleTimeString()
}, 1000)
const state = reactive({
city: "",
today: {},
show: false,
future: [],
data: []
})
const selectCity = ({ selectedOptions }) => {
// console.log(selectedOptions[1].text);
state.city = selectedOptions[1].text
getWeather(selectedOptions[1].text)
state.show = false
}
AMap.plugin('AMap.CitySearch', function () {
var citySearch = new AMap.CitySearch()
citySearch.getLocalCity(function (status, result) {
if (status === 'complete' && result.info === 'OK') {
// 查询成功,result即为当前所在城市信息
state.city = result.city
getWeather(result.city)
}
})
})
const getWeather = (city) => {
//加载天气查询插件
AMap.plugin("AMap.Weather", function () {
//创建天气查询实例
var weather = new AMap.Weather();
//执行实时天气信息查询
weather.getLive(city, function (err, data) {
console.log(err, data);
//err 正确时返回 null
//data 返回实时天气数据,返回数据见下表
state.today = data
});
weather.getForecast(city, function (err, data) {
console.log(err, data);
//err 正确时返回 null
//data 返回天气预报数据,返回数据见下表
state.future = data.forecasts.slice(1, 3)
// console.log(state.future[0]);
state.data = data.forecasts
// initEcharts()
nextTick(() => {
initEcharts(data.forecasts.map(item => item.dayTemp))
})
});
});
}
10. 样式美化
最后在样式部分,添加CSS代码来美化界面。
.container {
min-height: 100vh;
background-color: skyblue;
background: url("https://img1.baidu.com/it/u=771077137,4076319259&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=889");
background-size: cover;
opacity: 0.7;
color: white;
}
.nav {
display: flex;
justify-content: space-between;
padding: 20px;
}
.city-info {
text-align: center;
font-size: 18px;
}
p {
margin-top: 10px;
}
.weather {
font-size: 40px;
}
.temp {
font-size: 28px;
margin: 10px 0;
}
.font {
display: block;
font-size: 18px;
margin-top: 35px;
}
.temp em {
font-size: 34px;
}
.detail span {
margin: 0 7px;
font-size: 15px;
}
.future {
margin: 0 10px;
margin-top: 30px;
}
.group {
height: 44px;
line-height: 44px;
background-color: rgba(255, 255, 255, 0.3);
font-size: 13px;
padding: 0 10px;
margin-bottom: 10px;
border-radius: 5px;
}
.echarts-wrap {
width: 100%;
height: 50vh;
/* colot: white; */
}
通过以上步骤,我们已经创建了一个简单但实用的天气预报应用。用户可以通过选择城市来查看该地区的实时天气和未来天气预报。
总结
通过这次实战项目,我深刻体会到了将理论知识应用于实际开发的重要性。从项目初始化到最终成品的每一个环节,我都经历了从概念理解到动手实践的过程,这不仅巩固了我的编程基础,也大大提升了我的问题解决能力和创新思维。
具体而言,我学会了如何使用Vue CLI快速搭建项目骨架,理解了Vue.js的响应式原理及其在实际项目中的运用,掌握了组件化开发的思想,以及如何合理组织项目结构。在集成第三方库方面,如Vant UI和ECharts,我学会了按需引入和使用组件,这让我认识到在实际开发中选择合适工具的重要性。
此外,通过接入高德地图API获取天气数据,我熟悉了API的调用流程,包括请求参数的设置、数据解析和错误处理,这增强了我的网络通信和数据处理能力。在实现城市选择器和天气信息展示的过程中,我进一步提高了对Vue响应式系统和DOM操作的理解。
最重要的是,这个实战项目锻炼了我的自学能力和独立解决问题的能力,我学会了如何查阅官方文档,如何利用社区资源,以及如何调试和优化代码。这对我个人的技术成长有着不可估量的价值。
总之,这次实战经历不仅是一次技术上的挑战,更是一次自我提升的旅程,让我在实践中学习,在学习中成长。我相信,这段经历将为我未来的职业发展奠定坚实的基础。