☁
今天带大家用vue框架实现简易的天气预报页面。
准备步骤我就不过多赘述,详情可以参考# Vue3项目搭建与基础知识详解这篇文章。
index.js
首先,在index.js
文件下添加以下代码:
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [{
path:'/',
component: () => import('../views/Index.vue')
}]
})
export default router
这段代码创建了一个vue路由器实例,通过路径为:'/' 的主页导入组件,组件文件路径为:'../views/Index.vue'
,通过router接收,然后通过export default router抛出。
main.js
然后在main.js
文件下添加以下代码:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import './assets/reset.css'
const app = createApp(App)
app.use(router)
app.mount('#app')
-
import { createApp } from 'vue': 从Vue.js库中导入
createApp
函数,用来创建Vue应用实例。 -
import App from './App.vue': 这行代码导入应用根组件
App.vue
。 -
import router from './router': 这里导入之前抛出的路由配置。
-
import './assets/reset.css': 导入全局CSS样式文件
reset.css
,重置浏览器默认样式。# CSS Tools: Reset CSS,需要可自取。
-
const app = createApp(App): 创建一个以
App
作为根组件的Vue应用实例。 -
app.use(router).mount('#app'): 使用路由实例,并绑定在HTML中id='app'的元素上。
App.vue
代码如下:
<template>
<div>
</div>
<router-view></router-view>
</template>
<script setup>
</script>
<style lang="css" scoped>
</style>
<router-view></router-view>
为路由入口,根据url的变化,不同的组件会被渲染在这个位置。
Index.vue
import { reactive, ref } from 'vue'
import { areaList } from '@vant/area-data';
const selectCity = ({ selectedOptions }) => {
console.log(selectedOptions[1].text)
state.city = selectedOptions[1].text
getWeather(state.city)
state.show = false
}
import { reactive, ref, nextTick } from 'vue':
reactive()
: 这个函数用于创建一个响应式的对象。它接受一个普通的JavaScript对象作为参数,并返回一个响应式的版本。ref()
: 这个函数用于创建一个响应式的引用类型,通常用于简单的值如字符串、数字或布尔值。ref
返回一个对象,该对象具有一个.value
属性,用于获取和设置值。nextTick()
: 这是一个异步函数,用于在DOM更新完成后执行回调函数。
import { areaList } from '@vant/area-data';:
- 从
@vant/area-data
模块导入了areaList
。@vant/area-data
是Vant 框架提供的地区数据包,包含了中国的省份、城市和区县的详细信息。areaList
是一个对象或数组,可以用来构建地区选择器或下拉菜单等界面组件,让用户能够位置信息。 ⚠:需要在终端命令行输入:npm i @vant/area-data
,安装 @vant/area-data 包来引入数据。
这里的意图是创建一个地区选择器,允许用户从预定义的地区列表中选择他们所在的省份、城市和区县。使用reactive
和ref
可以帮助你更灵活地管理用户的选择状态,并响应这些状态的改变以更新UI。
import * as echarts from 'echarts':导入ECharts
库,用于创建图表。
import { onMounted } from 'vue':导入Vue的生命周期钩子,用于初始化Echarts图表。
let now = ref('00:00:00')
setInterval(() => {
now.value = new Date().toLocaleTimeString()
}, 1000);
然后定义一个变量now接收ref
创建的一个初始值为'00:00:00'
的响应式引用。然后用setInterval方法设置一个定时器,每隔1秒执行一次。在每次执行时,now.value会被更新为当前系统时间的字符串表示形式,格式化为本地时间格式。new Date().toLocaleTimeString()
是一个JS方法,用于获取当前时间的本地化字符串表示。
const state = reactive({
city: '',
today: {},
show: false,
tomorrow: {},
aftertomorrow: {}
})
然后设置状态state:
city
:空字符串,用于存储用户选择的城市名称。today
:空对象,用于存储当天的天气信息。show
:布尔值,初始为false
,用于控制显示和隐藏地区选择栏。tomorrow
:空对象,用于存储预测的明天的天气信息。aftertomorrow
:空对象,用于存储预测的后天的天气信息。
AMap.plugin('AMap.CitySearch', function () {
var citySearch = new AMap.CitySearch()
citySearch.getLocalCity(function (status, result) {
if (status === 'complete' && result.info === 'OK') {
// 查询成功,result即为当前所在城市信息
console.log(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);
state.today = data
});
});
//加载天气查询插件
AMap.plugin("AMap.Weather", function () {
//创建天气查询实例
var weather = new AMap.Weather();
//执行实时天气信息查询
weather.getForecast(city, function (err, data) {
console.log(err, data);
state.tomorrow = data.forecasts[1]
state.aftertomorrow = data.forecasts[2]
nextTick(() => { // 保证内部的逻辑会在页面渲染完毕后执行
initEcharts(data.forecasts.map(item => item.dayTemp))
})
});
});
}
用高德地图插件CitySearch
来获取用户当前所在的城市信息,并将获取到的城市名称存储到之前定义的状态state中。定义citySearch
实例。变量来接收new AMap.CitySearch()
对象,创建citySearch
实例。
调用该插件中的getLocalCity()
方法实施定位,获取用户的位置信息。查询成功后输出用户的位置信息,并将结果result
的city
属性赋值给state
对象中city
属性。然后调用getWeather()
方法获取当地的天气信息。
定义getWeather()
函数,接收city作为参数,然后调用高德地图插件中Weather
的getLive
和
getForecast
方法获取指定的城市的当天和预测未来3天的天气信息。但是由于我们只设置了明天和后天的状态,所以只接收了明后两天的天气信息。当查询成功后更新state中的today
,tomorrow
,aftertomorrow
的信息。
接着调用nextTick(() => {initEcharts(data.forecasts.map(item => item.dayTemp))})
初始化Echarts图表,并将data.forecasts
的dayTemp
属性传递给initEcharts()
函数。
const selectCity = ({ selectedOptions }) => {
console.log(selectedOptions[1].text)
state.city = selectedOptions[1].text
getWeather(state.city)
state.show = false
}
定义selectCity()
函数,接收selectedOptions[1].text
属性,为城市名称。
selectedOptions
来自<van-area>
组件的事件处理器,<van-area>
是Vant库中的一个组件,用于展示地区选择器,允许用户选择省市区等地理区域。当用户在地区选择器中做出选择并确认选择时,<van-area>
组件会触发一个confirm
事件。在你的代码中,这个事件处理器被定义为selectCity
函数。confirm
事件会传递一个对象作为参数,这个对象包含了用户选择的地区信息,其中selectedOptions
属性是一个数组,包含了用户选择的地区层级(如省、市、区)的详细信息。这个会在后续完整代码中展示出来。
将selectedOptions[1].text
的值传给state.city
,然后调用getWeather()
方法,获取你选择的城市的天气信息,通过设置state.show = false
来控制选择城市完成后隐藏地区选择栏,提升用户体验。
const echartsWrap = ref(null)
const initEcharts = (arr) => {
// console.log(echartsWrap.value);
let myChart = echarts.init(echartsWrap.value)
myChart.setOption({
tooltip: {},
xAxis: {
type: 'category',
data: ['今天', '明天', '后天', '大后天']
},
yAxis: {},
series: [
{
name: '温度',
type: 'line',
data: arr
}
]
});
}
定义echartsWrap
变量接收ref
创建的一个初始值为null的响应式引用。
定义 initEcharts()
函数,接收arr作为参数,并初始化图表
定义变量myChart
接收echartsWrap.value
,也就是echartsWrap
引用所指向的DOM元素。
初始化图表后,使用setOption
方法来设置图表的配置选项。
xAxis
设置了x轴的类型为category
,数据点为['今天', '明天', '后天', '大后天']
。yAxis
为空对象,会根据数据自动调整。series
设置了一个名为温度的数据系列,类型为line
(即为折线图),并使用arr
作为数据源,映射成折线图上的点。
完整Index.vue代码:
<template>
<div class="container">
<div class="nav">
<div class="time">{{ now }}</div>
<div class="city" @click="state.show = true">切换城市</div> //通过点击"切换城市"触发显示地区选择栏
</div>
<div class="city-info">
<p class="city">{{ state.city }}</p>
<p class="weather">{{ state.today.weather }}</p>
<h2 class="temp">
<em>{{ state.today.temperature }}</em>℃
</h2>
<div class="detail">
<span>风力:{{ state.today.windPower }} 级| </span>
<span> 风向:{{ state.today.windDirection }} 风| </span>
<span>空气湿度: {{ state.today.humidity }}%</span>
</div>
<div class="future">
<div class="group">
明天:
<span class="tm">白天:{{ state.tomorrow.dayTemp }}℃
{{ state.tomorrow.dayWeather }}
{{ state.tomorrow.dayWindDir }}
{{ state.tomorrow.dayWindPower }}</span>
<span class="tm">夜间:{{ state.tomorrow.nightTemp }}℃
{{ state.tomorrow.nightWeather }}
{{ state.tomorrow.nightWindDir }}
{{ state.tomorrow.nightWindPower }}</span>
</div>
<div class="group">
后天:
<span class="tm">白天:{{ state.aftertomorrow.dayTemp }}℃
{{ state.aftertomorrow.dayWeather }}
{{ state.aftertomorrow.dayWindDir }}
{{ state.aftertomorrow.dayWindPower }}</span>
<span class="tm">夜间:{{ state.aftertomorrow.nightTemp }}℃
{{ state.aftertomorrow.nightWeather }}
{{ state.aftertomorrow.nightWindDir }}
{{ state.aftertomorrow.nightWindPower }}</span>
</div>
</div>
</div>
<div class="echarts-wrap" ref="echartsWrap"></div>
<van-action-sheet v-model:show="state.show">
<div class="content">
<van-area title="地区" :area-list="areaList" :columns-num="2"
@confirm="selectCity" //当用户在地区选择器中做出选择并点击确认按钮时,会触发`selectCity`函数。这个函数负责处理用户的选择,通常会更新应用的状态,如更新当前选择的城市。
@cancel="state.show = false" />
</div>
</van-action-sheet>
</div>
</template>
<script setup>
import { reactive, ref, nextTick } from 'vue'
import { areaList } from '@vant/area-data';
import * as echarts from 'echarts';
import { onMounted } from 'vue';
let now = ref('00:00:00')
setInterval(() => {
now.value = new Date().toLocaleTimeString()
}, 1000);
const state = reactive({
city: '',
today: {},
show: false,
tomorrow: {},
aftertomorrow: {}
})
AMap.plugin('AMap.CitySearch', function () {
var citySearch = new AMap.CitySearch()
citySearch.getLocalCity(function (status, result) {
if (status === 'complete' && result.info === 'OK') {
// 查询成功,result即为当前所在城市信息
console.log(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);
state.today = data
});
});
//加载天气查询插件
AMap.plugin("AMap.Weather", function () {
//创建天气查询实例
var weather = new AMap.Weather();
//执行实时天气信息查询
weather.getForecast(city, function (err, data) {
console.log(err, data);
state.tomorrow = data.forecasts[1]
state.aftertomorrow = data.forecasts[2]
nextTick(() => { // 保证内部的逻辑会在页面渲染完毕后执行
initEcharts(data.forecasts.map(item => item.dayTemp))
})
});
});
}
const selectCity = ({ selectedOptions }) => {
console.log(selectedOptions[1].text)
state.city = selectedOptions[1].text
getWeather(state.city)
state.show = false
}
const echartsWrap = ref(null)
const initEcharts = (arr) => {
// console.log(echartsWrap.value);
let myChart = echarts.init(echartsWrap.value)
myChart.setOption({
tooltip: {},
xAxis: {
type: 'category',
data: ['今天', '明天', '后天', '大后天']
},
yAxis: {},
series: [
{
name: '温度',
type: 'line',
data: arr
}
]
});
}
// onMounted(()=>{
// initEcharts(data)
// })
</script>
<style lang="css" scoped> // 样式设置
.container {
min-height: 100vh;
background-color: #000;
opacity: 0.7;
color: #fff;
}
.nav {
display: flex;
justify-content: space-between;
padding: 20px;
}
.city-info {
text-align: center;
}
p {
margin-top: 10px;
}
.temp {
font-size: 30px;
margin: 10px 0;
}
.temp em {
font-size: 34px;
}
.future {
margin-top: 30px;
padding: 0 10px;
}
.group {
height: 40px;
line-height: 44px;
background-color: rgba(255, 255, 255, 0.5);
font-size: 13px;
padding: 0 10px;
margin-bottom: 10px;
border-radius: 5px;
}
.echarts-wrap {
width: 100%;
height: 50vh;
}
</style>
实现效果如下:
因为这个页面使用了高德地图的定位服务,需要导入相应的插件,所以需要获取安全密钥和APIKey并存储到HTML中。HTML代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
<script type="text/javascript">
window._AMapSecurityConfig = {
securityJsCode: "「你申请的安全密钥」", };
</script>
<script type="text/javascript" src="https://webapi.amap.com/maps?v=2.0&key=你申请的key值" >
</script>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
本文引入的Echarts库,Vant库以及所需的高德地图插件使用方法等可在以下链接中查看相关文档查找。