11.基于Vue的网络框架 vue-axios的应用

互联网有许多第三方API接口服务,使用这些我们可以很方便的开发个人使用的工具

使用vue-axios进行数据请求

axios本身是一个基于promise的HTTP客户端工具,vue-axios针对Vue对axios进行了一层简单的包装。

promise ES6特有的.then正常的回调函数 .catch发生错误时的回调函数

首先在vue项目工程下进行vue-axios模块的安装

1
2
3
4
# npm 安装
npm install --save axios vue-axios
# 使用 cdn:
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

安装完成后,可以检查package.json文件中是否已经添加了vue-axios的依赖,我们还需要在main.js文件中对其进行导入和注册

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 导入vue-axios模块
import VueAxios from 'vue-axios'
import axios from 'axios'

import { createApp } from 'vue'
// 导入我们自定义的根组件
import App from './App.vue'

// createApp(App).mount('#app')
// 挂载根组件
const app = createApp(App)
// 注册axios
app.use(VueAxios,axios)
app.mount("#app")

vue-axios实用功能介绍

vue-axios中提供了许多快捷请求方法,其中url参数是请求的接口,config参数是选填的,用来配置请求的额外选项。

1
2
3
4
5
6
7
8
axios.request(config)
axios.get(url[, config])
axios.delete(url[, config])
axios.head(url[, config])
axios.options(url[, config])
axios.post(url[, data[, config]])
axios.put(url[, data[, config]])
axios.patch(url[, data[, config]])
  1. 发送 GET 请求:使用 Axios 发送 GET 请求:
1
2
3
4
5
6
7
axios.get('https://api.example.com/data')
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error(error);
});
  1. 发送 POST 请求:使用 Axios 发送 POST 请求:
1
2
3
4
5
6
7
axios.post('https://api.example.com/data', { name: 'John', age: 30 })
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error(error);
});
  1. 拦截器:可以使用 Axios 的拦截器来在请求和响应被处理前进行一些操作,例如添加请求头或处理错误:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
axios.interceptors.request.use(config => {
// 在请求发送之前做些什么
return config;
}, error => {
// 对请求错误做些什么
return Promise.reject(error);
});

axios.interceptors.response.use(response => {
// 对响应数据做点什么
return response;
}, error => {
// 对响应错误做点什么
return Promise.reject(error);
});

Axios 提供了丰富的功能和选项,如请求和响应拦截、取消请求、设置请求超时等。它的简单易用性和丰富的功能使得它成为在 Vue 项目中进行 HTTP 请求的首选工具之一。

除了这些快捷方法外,可以通过向 axios API 传递相关配置来创建请求

axios(config)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 发送 POST 请求
axios({
method: 'post',
url: '/user/12345',
data: {
firstName: 'Fred',
lastName: 'Flintstone'
}
});
// 获取远端图片
axios({
method:'get',
url:'http://bit.ly/2mTM3nY',
responseType:'stream'
})
.then(function(response) {
response.data.pipe(fs.createWriteStream('ada_lovelace.jpg'))
});

axios(url[, config])

1
2
// 发送 GET 请求(默认的方法)
axios('/user/12345');

使用vue-axios请求天气数据

我们需要使用到element-plus

1
2
npm install element-plus --save
npm install --save axios vue-axios

main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 导入Vue框架中的createApp方法
import { createApp } from 'vue'
// 导入我们自定义的根组件
import App from './App.vue'
// 导入路由需要用到的自定义组件
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import VueAxios from 'vue-axios'
import axios from 'axios'

// 挂载根组件
const app = createApp(App)
// 注册路由
app.use(ElementPlus)
app.use(VueAxios,axios)
// 进行应用挂载
app.mount("#app")

App.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
<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.textDay || plc }} {{ todayData.tempMax || plc }}-{{ todayData.tempMin || plc }}</span>
<span style="margin-left:20px">{{ todayData.windDirDay || plc }}</span>
<span style="margin-left:100px">{{ formatFxDate(todayData.fxDate) }}</span>
</div>
<div class="real">
<span class="temp">{{ todayData.tempMin || plc }}°</span>
<span class="realInfo">{{ todayData.weather || plc }}</span>
<span class="realInfo" style="margin-left:20px">{{ todayData.windDirDay || plc }}</span>
<span class="realInfo" style="margin-left:20px">{{ todayData.windScaleDay || plc }}</span>
</div>
<div class="real">
<span class="realInfo">空气质量:{{ todayData.aqi || plc }}</span>
<span class="realInfo" style="margin-left:20px">湿度:{{ todayData.humidity || plc }}%</span>
</div>
<div class="future">
<div class="header">3日天气预报</div>
<el-table :data="futureData" style="margin-top:30px">
<el-table-column prop="fxDate" label="日期" :formatter="futureData.fxDate"></el-table-column>
<el-table-column prop="tempRange" label="温度"></el-table-column>
<el-table-column prop="textDay" label="天气"></el-table-column>
<el-table-column prop="windDirDay" 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>
<script>
import axios from 'axios';

export default {
// 当组件被挂载到 DOM 上时执行
mounted() {
// 设置全局的 axios 基本 URL
axios.defaults.baseURL = 'https://devapi.qweather.com';
// 请求天气数据
this.requestID();
},
data() {
return {
city: "上海", // 用户输入的城市名称
cityID: "101020100", // 默认城市代码(上海)
daily: [], // 存储每日天气数据的数组
todayData: {}, // 存储当天的天气数据
plc: "暂无数据", // 当数据不可用时的占位符
futureData: [] // 存储未来天气数据的数组
}
},
watch: {
city() {
// 当 city 发生变化时,重新请求城市ID
this.requestID();
}
},
methods: {
// 获取城市ID
requestID() {
// 如果 city 为空,则使用默认的 cityID
if (!this.city) {
this.cityID = "101020100"; // 默认值(上海)
this.requestData(); // 请求天气数据
return;
}
const city = encodeURI(this.city); // 对城市名进行 URL 编码
const api = `https://geoapi.qweather.com/v2/city/lookup?location=${city}&key=ae196721c8f8你的ApiKey`;
axios.get(api)
.then((response) => {
this.cityID = response.data.location[0].id; // 设置 cityID
this.requestData(); // 请求天气数据
})
.catch((error) => {
console.error('Request ID failed:', error);
});
},
// 根据城市ID获取城市天气
requestData() {
const api = `/v7/weather/3d?location=${this.cityID}&key=ae196721c8f8你的ApiKey`;
axios.get(api)
.then((response) => {
this.daily = response.data.daily || [];
this.todayData = this.daily[0] || {}; // 设置今天的天气数据
this.prepareFutureData(); // 准备未来几天的天气数据
})
.catch((error) => {
console.error('Request weather data failed:', error);
});
},
// 格式化未来几天的天气数据
prepareFutureData() {
this.futureData = this.daily.map(day => ({
fxDate: this.formatFxDate(day.fxDate), // 格式化日期
tempRange: `${day.tempMax} - ${day.tempMin}`, // 温度范围
textDay: day.textDay, // 白天天气情况
windDirDay: day.windDirDay // 白天风向
}));
},
// 格式化日期
formatFxDate(date) {
if (typeof date === 'string') {
return date.replace(/-/g, '/'); // 将日期中的 '-' 替换为 '/'
}
return '日期未知';
}
}
}
</script>
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
{
"code": "200",
"location": [
{
"name": "上海",
"id": "101020100",
"lat": "31.23171",
"lon": "121.47264",
"adm2": "上海",
"adm1": "上海市",
"country": "中国",
"tz": "Asia/Shanghai",
"utcOffset": "+08:00",
"isDst": "0",
"type": "city",
"rank": "11",
"fxLink": "https://www.qweather.com/weather/shanghai-101020100.html"
},
{
"name": "闵行",
"id": "101020200",
"lat": "31.11166",
"lon": "121.37597",
"adm2": "上海",
"adm1": "上海市",
"country": "中国",
"tz": "Asia/Shanghai",
"utcOffset": "+08:00",
"isDst": "0",
"type": "city",
"rank": "25",
"fxLink": "https://www.qweather.com/weather/minhang-101020200.html"
},
{
"name": "宝山",
"id": "101020300",
"lat": "31.39890",
"lon": "121.48994",
"adm2": "上海",
"adm1": "上海市",
"country": "中国",
"tz": "Asia/Shanghai",
"utcOffset": "+08:00",
"isDst": "0",
"type": "city",
"rank": "23",
"fxLink": "https://www.qweather.com/weather/baoshan-101020300.html"
},
],
"refer": {
"sources": [
"QWeather"
],
"license": [
"QWeather Developers License"
]
}
}
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
{
"code": "200",
"updateTime": "2023-12-28T12:35+08:00",
"fxLink": "https://www.qweather.com/weather/shanghai-101020100.html",
"daily": [
{
"fxDate": "2023-12-28",
"sunrise": "06:52",
"sunset": "17:00",
"moonrise": "18:04",
"moonset": "08:08",
"moonPhase": "亏凸月",
"moonPhaseIcon": "805",
"tempMax": "14",
"tempMin": "7",
"iconDay": "104",
"textDay": "阴",
"iconNight": "154",
"textNight": "阴",
"wind360Day": "0",
"windDirDay": "北风",
"windScaleDay": "1-3",
"windSpeedDay": "3",
"wind360Night": "0",
"windDirNight": "北风",
"windScaleNight": "1-3",
"windSpeedNight": "3",
"humidity": "88",
"precip": "0.0",
"pressure": "1026",
"vis": "25",
"uvIndex": "3",
"pop": "20"
},
{
"fxDate": "2023-12-29",
"sunrise": "06:52",
"sunset": "17:01",
"moonrise": "19:02",
"moonset": "08:52",
"moonPhase": "亏凸月",
"moonPhaseIcon": "805",
"tempMax": "14",
"tempMin": "8",
"iconDay": "100",
"textDay": "晴",
"iconNight": "150",
"textNight": "晴",
"wind360Day": "0",
"windDirDay": "北风",
"windScaleDay": "1-3",
"windSpeedDay": "3",
"wind360Night": "0",
"windDirNight": "北风",
"windScaleNight": "1-3",
"windSpeedNight": "3",
"humidity": "91",
"precip": "0.0",
"pressure": "1019",
"vis": "25",
"uvIndex": "3",
"pop": "5"
},
{
"fxDate": "2023-12-30",
"sunrise": "06:52",
"sunset": "17:01",
"moonrise": "20:00",
"moonset": "09:28",
"moonPhase": "亏凸月",
"moonPhaseIcon": "805",
"tempMax": "13",
"tempMin": "6",
"iconDay": "305",
"textDay": "小雨",
"iconNight": "150",
"textNight": "晴",
"wind360Day": "0",
"windDirDay": "北风",
"windScaleDay": "1-3",
"windSpeedDay": "3",
"wind360Night": "315",
"windDirNight": "西北风",
"windScaleNight": "1-3",
"windSpeedNight": "16",
"humidity": "50",
"precip": "0.0",
"pressure": "1021",
"vis": "25",
"uvIndex": "3",
"pop": "25"
}
],
"refer": {
"sources": [
"QWeather"
],
"license": [
"CC BY-SA 4.0"
]
}
}

axios获取天气

Script 部分解释:

这段代码是从一个 API 获取天气数据,并对这些数据进行处理以显示在 Vue 应用中。我将逐一解释这段代码的每个部分。

导入 Axios:

1
import axios from 'axios';
  • 作用:从 axios 库中导入 axios 对象。axios 是一个流行的 HTTP 客户端,用于发送 HTTP 请求。

Vue 组件导出:

1
2
3
export default {
// 组件生命周期钩子和数据定义...
}
  • 作用:定义并导出一个 Vue 组件。

Mounted 生命周期钩子:

1
2
3
4
mounted() {
axios.defaults.baseURL = 'https://devapi.qweather.com';
this.requestID();
}
  • 作用:当组件被挂载到 DOM 上时执行。
  • axios.defaults.baseURL:设置 axios 的全局基本 URL。所有的 axios 请求都会使用这个 URL 作为前缀。
  • this.requestID():调用 requestID 方法来初始化天气数据的请求。

Data 函数:

1
2
3
4
5
data() {
return {
// 数据定义...
}
}
  • 作用:定义组件的响应式数据。
  • city:用户输入的城市名称。
  • cityID:城市的标识符,默认为上海。
  • daily, todayData, plc, futureData:分别用于存储每日天气数据、当天天气数据、无数据时的占位符和未来天气预报数据。

Watch 属性:

1
2
3
4
5
watch: {
city() {
this.requestID();
}
}
  • 作用:监听 city 属性的变化。
  • this.requestID():当 city 发生变化时,调用 requestID 方法以获取新的城市ID并请求相应的天气数据。

requestID 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 获取城市ID
requestID() {
// 如果 city 为空,则使用默认的 cityID
if (!this.city) {
this.cityID = "101020100"; // 默认值(上海)
this.requestData(); // 请求天气数据
return;
}
const city = encodeURI(this.city); // 对城市名进行 URL 编码
const api = `https://geoapi.qweather.com/v2/city/lookup?location=${city}&key=ae196721c8f8你的ApiKey`;
axios.get(api)
.then((response) => {
this.cityID = response.data.location[0].id; // 设置 cityID
this.requestData(); // 请求天气数据
})
.catch((error) => {
console.error('Request ID failed:', error);
});
}
  • 作用: 获取用户输入的城市的ID。

  • 流程:

    • 检查 city 是否为空。如果为空,使用默认的城市ID(上海)并请求天气数据。
    • 如果 city 不为空,将城市名进行 URL 编码,构建查询城市ID的 API 请求。
    • 使用 axios.get 向 API 发送请求。
    • 请求成功后,从响应中提取城市ID,并用它请求天气数据。
    • 如果请求失败,输出错误信息到控制台。

requestData 方法:

这个方法的目的是向一个天气 API 发送请求,获取指定城市的天气数据。

1
2
3
4
5
6
7
8
9
10
11
12
requestData() {
const api = `/v7/weather/3d?location=${this.cityID}&key=ae196721c8f8你的ApiKey`;
axios.get(api)
.then((response) => {
this.daily = response.data.daily || [];
this.todayData = this.daily[0] || {}; // 设置今天的天气数据
this.prepareFutureData(); // 准备未来几天的天气数据
})
.catch((error) => {
console.error('Request weather data failed:', error);
});
}
  • API URL: 使用模板字符串构建 API 请求的 URL。这里 this.cityID 是城市的标识符,用于获取特定城市的天气。

  • axios.get: 发送一个 GET 请求到上面构建的 URL。Axios 是一个流行的 HTTP 客户端库。

  • .then()

    : 当请求成功时执行。

    1
    response

    对象包含 API 返回的数据。

    • response.data.daily: 从 API 响应中获取天气数据,通常是一个数组,其中每个元素代表一天的天气。
    • this.daily: 存储从 API 获取的天气数据。
    • this.todayData: 存储数组中的第一个元素,即今天的天气数据。
    • this.prepareFutureData(): 调用另一个方法来处理和格式化未来几天的天气数据。
  • .catch(): 如果请求失败(例如,因为网络问题或服务器错误),则执行错误处理。

prepareFutureData 方法:

这个方法用于处理和格式化未来几天的天气数据,以便在 Vue 应用中显示。

1
2
3
4
5
6
7
8
prepareFutureData() {
this.futureData = this.daily.map(day => ({
fxDate: this.formatFxDate(day.fxDate), // 格式化日期
tempRange: `${day.tempMax} - ${day.tempMin}`, // 温度范围
textDay: day.textDay, // 白天天气情况
windDirDay: day.windDirDay // 白天风向
}));
}
  • Array.map(): 这是 JavaScript 中的一个数组方法,用于将数组中的每个元素通过一个函数映射(转换)为新的元素,最终返回一个新的数组。
  • day: map 方法的回调函数接收 daily 数组中的每个元素作为参数 dayday 是一个对象,包含了特定日期的天气数据。
  • map 方法的回调函数中,创建了一个新的对象,其中包含格式化的日期、温度范围、白天的天气情况和风向。
  • this.futureData: 最终,this.futureData 被赋值为 map 方法返回的新数组,这个数组包含了格式化后的未来天气数据。

formatFxDate 方法

1
2
3
4
5
6
7
// 格式化日期
formatFxDate(date) {
if (typeof date === 'string') {
return date.replace(/-/g, '/'); // 将日期中的 '-' 替换为 '/'
}
return '日期未知';
}
  • 作用: 将日期字符串中的 - 替换为 /,以便更友好地展示日期。

  • 流程

    :

    • 检查传入的 date 是否为字符串类型。
    • 如果是字符串,则使用 replace 方法进行格式化。
    • 如果不是字符串,返回默认字符串“日期未知”。

总结来说,requestData 方法从 API 获取天气数据,并存储在组件的数据属性中。然后,prepareFutureData 方法处理这些数据,将其转换为一个更易于在应用中显示的格式。map 方法在这里被用于创建一个新的数组,其中的每个元素都是通过 day 参数进行转换的结果。