coder-Tom

一个喜欢代码, 音乐,读书, 跑步, 记录生活的程序员

0%

用vue实现一个简单的天气预报

用vue实现一个简单的天气预报项目:

App.vue:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
<div id="app">
<keep-alive>
<router-view /> 路由出口
</keep-alive>
<!-- 底部tabbar -->
<!-- <HelloWorld /> -->
</div>
</template>

<script>


export default {
name: "App",

};
</script>

<style lang="scss">
</style>

main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import getApi from "./api";
import "@/assets/css/normalize.css";
import ElementUI from "element-ui";
import "element-ui/lib/theme-chalk/index.css";
Vue.config.productionTip = false;

// 将api请求注入原型对象中(全局化)
Vue.prototype.$api = getApi;

// 项目中用到了elementUI
Vue.use(ElementUI);

new Vue({
router,
store,
render: (h) => h(App),
}).$mount("#app");

其实对于这个项目, 我们最困难的就是服务之类的了, 这项项目的页面很简洁, 也就几个主要组件, 接下来我们看看请求部分,我们需要使用到axios, 先安装axios

1
"axios": "^0.24.0",

那么接下来的代码主要用到的就是axios的知识:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import axios from "axios";   //引入axios
import router from "@/router"; //引入路由
import { Message, Loading } from "element-ui"; //引入element-ui
//设置接口i
const api_base_url = "https://bird.ioliu.cn";

// 创建axios实例
let instance = axios.create({
time: 1000 * 60,
baseURL: api_base_url,
});
let loadingInstance; //加载中。。。
// 请求拦截器
instance.interceptors.request.use(
(config) => {
loadingInstance = Loading.service({
text: "拼命加载中~",
});
return config;
},
(error) => {
loadingInstance.close();
Message.error({ message: "请求超时!" });
return Promise.reject(error);
}
);

// 响应拦截器即异常处理
instance.interceptors.response.use(
(response) => {
loadingInstance.close();
let data = response.data;
let status = response.status;
if (status === 200) {
return Promise.resolve(data);
} else {
Message.error({ message: "服务器好像出了些问题~" });
return Promise.reject(response);
}
},
(error) => {}
);

export default instance;

设置获取天气数据的函数:

1
const getCityWeather = (city) => api.get(`/weather?city=${city}`);

home.vue(页面主要代码)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
<template>
<div class="home" :style="{ backgroundImage: 'url(' + coverImgUrl + ')' }">
<div class="weather-box">
<el-cascader
size="medium"
separator=">"
:options="options"
placeholder="请选择/搜索"
v-model="selectedOptions"
:props="{ expandTrigger: 'hover' }"
filterable
@change="selectCity"
/>
<div class="now-cond" v-if="Object.keys(weathData).length">
<p class="address">
<i class="el-icon-place" />{{ weathData.basic.city }}
</p>
<p class="upTime">{{ weathData.basic.update.loc }}</p>
<i class="condTxt">{{ weathData.now.cond.txt }}</i>
<p class="wind">{{ weathData.now.wind.dir }}</p>
<p class="tmp">
{{ weathData.daily_forecast[0].tmp.min }}℃~{{
weathData.daily_forecast[0].tmp.max
}}℃
</p>
<h1>未来3日天气预报</h1>
<el-table
:data="weathData.daily_forecast"
border
style="width: 100%"
stripe
>
<el-table-column label="日期" width="180">
<template slot-scope="scope">
<i class="el-icon-time"></i>
<span style="margin-left: 10px">{{ scope.row.date }}</span>
</template>
</el-table-column>
<el-table-column prop="cond.txt_d" label="天气" />
<el-table-column prop="tmp.min" label="最低温度(℃)" width="120" />
<el-table-column prop="tmp.max" label="最高温度(℃)" width="120" />
<el-table-column prop="wind.dir" label="风向" />
</el-table>
</div>
<div class="tip" v-else>
<h1>选择城市开始查询吧</h1>
</div>
</div>
</div>
</template>

<script>
//城市选择
import { regionData, CodeToText } from "element-china-area-data";

export default {
name: "Home",
data() {
return {
options: regionData,
selectedOptions: [],
addressAll: [],
address: "",
weathData: {},
coverImgUrl: require("@/assets/img/bg.jpg"),
};
},
methods: {
//选择地区
selectCity() {
this.addressAll = [];
this.selectedOptions.forEach((city) => {
this.addressAll.push(CodeToText[city]);
});
this.inquireWeather();
},
// 点击天气查询
async inquireWeather() {
if (this.addressAll[2] == "市辖区" || this.addressAll.length == 2) {
this.address = this.addressAll[1]; //如果选市辖区就定位到二级地址
} else {
this.address = this.addressAll[2]; //区域码所对应的属性值即中文地址
}
// 开始请求接口
const res1 = await this.$api.getCityWeather(this.address);
if (res1.status === "ok") {
//请求数据成功
this.$notify({
title: "查询成功",
type: "success",
});
this.weathData = res1;
this.weathData.daily_forecast.shift();
this.weathData.daily_forecast.splice(3, 3);
//无法找到该地
} else if (res1.status === "unknown location") {
// 1.只是无法获取到三级地址信息
// 重新请求上一级地址
this.address = this.addressAll[1];
const res2 = await this.$api.getCityWeather(this.address);
if (res2.status === "ok") {
this.$notify({
title: "查询成功",
type: "success",
});
this.weathData = res2;
this.weathData.daily_forecast.shift();
this.weathData.daily_forecast.splice(3, 3);
} else {
// 重新请求上一级地址
this.address = this.addressAll[0];
const res3 = await this.$api.getCityWeather(this.address);
if (res3.status === "ok") {
this.$notify({
title: "查询成功",
type: "success",
});
this.weathData = res3;
this.weathData.daily_forecast.shift();
this.weathData.daily_forecast.splice(3, 3);
} else {
// 2.彻底无法找到该地
this.$message({
message: "抱歉,无法获取该地相关信息",
type: "error",
});
}
}
}
// 背景图片切换
this.bgChange();
},
// 背景图片切换
bgChange() {
const weather = this.weathData.now.cond.txt;
this.coverImgUrl = require(`@/assets/img/${weather}.jpg`);
},
},
};
</script>

<style lang="scss" scoped>
.home {
@mixin xy($top: auto, $right: auto, $bottom: auto, $left: auto) {
top: $top;
right: $right;
bottom: $bottom;
left: $left;
}
@mixin wh($wid, $hei) {
width: $wid;
height: $hei;
}
@mixin font($size, $fw: bold, $color: #fff) {
font-size: $size;
font-weight: $fw;
color: $color;
}
position: relative;
min-height: 100vh;
// background: url("~");
background-repeat: no-repeat;
background-position: center center;
background-size: cover;
.weather-box {
position: absolute;
text-align: center;
z-index: 999;
@include xy(5%, "", "", 50%);
transform: translateX(-50%);
.now-cond {
h1 {
@include font(20px);
}
.address,
.upTime {
@include font(20px);
text-shadow: 5px 5px 5px #000;
}
.condTxt {
@include font(80px, bolder);
text-shadow: 5px 5px 5px #ccc;
}
.wind,
.tmp {
@include font(20px, bolder, #000);
text-shadow: 2px 2px 5px rgb(144, 149, 216);
}
}
.tip {
h1 {
@include font(50px, bolder);
text-shadow: 2px 2px 5px rgb(144, 149, 216);
}
}
}
}
</style>

主要的代码都在上面,之前测试是可以的, 但是现在由于接口更新的问题, 现在可能访问不了:

效果就像是下面这样:

image-20230227163857686

大致的代码就是这样子的,也是一个简单的练手的一个小项目