Axios
Axios 是一个基于 Promise 的 HTTP 库,可以用在浏览器和 node.js 中。
Github开源地址: https://github.com/axios/axios
安装
[!tip]
vue3不要用
vue add axios
安装,不然会出现各种问题,且很难解决,网上给出的解决办法就是用vue2👎
# 其他组件
vue create hello-vue
cd hello-vue
vue add element-plus
vue add router
# axios
npm install --save axios # 安装后可以在package.json中查看安装的版本
安装后在main.js
中引入,参考文章:手把手教你在vue3中使用axios
import { createApp } from 'vue'
import App from './App.vue'
import installElementPlus from './plugins/element'
import router from './router'
import axios from "axios" // 引入
const app = createApp(App).use(router)
installElementPlus(app)
app.config.globalProperties.axios = axios // 将axios挂载到全局变量,后面可以通过 this.axios 调用
app.mount('#app')
使用
引入后就可以直接用了,注意是this.axios
,因为我们给挂载到全局变量了
<template>
<div class="about">
<h1 @click="test">This is an about page</h1>
</div>
</template>
<script>
export default {
methods: {
test() {
this.axios.get("http://127.0.0.1:8080",{a:"b"})
.then(res => {
console.log(res)
})
.catch(err => {
console.error(err);
})
}
},
}
</script>
用法就是get
、post
等,发起请求抓取数据即可,vscode装了插件都可以自动补全,比较方便
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]])
更多用法参考官方文档:axios中文文档
解决跨域问题
以某天气API http://t.weather.sojson.com/api/weather/city/101030100 为例,如果直接本地用axios发起get post请求,肯定是拿不到数据的,因为有CORS策略的限制。
要解决这个问题,有2个方法:
1、修改后端,添加header头信任任意来源(这里肯定没权限改别人的后端,所以有第二个方法)
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
2、可以通过Vue的proxy来解决跨域的问题
在vue.config.js
文件中,加入如下内容:
也可以在
main.js
中配置axios.defaults.baseURL
,自动加上代理的URL,减少每次写一遍代理URL的工作量
module.exports = {
publicPath:'./',//静态资源包打包为相对路径
outputDir:'dist',//输出文件
devServer:{
open:false,
host:'0.0.0.0',
port:8090,
hot:true,
proxy: {
'/api': {
target: 'http://t.weather.sojson.com/', // 需要请求的第三方接口地址
changeOrigin: true, // 是否跨域:在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题
ws: true, //是否代理 websockets
secure: false, //是否https接口
pathRewrite: { // 路径重写,
'^/api': '' // 替换target中的请求地址,也就是说以后你请求/api就等于请求http://t.weather.sojson.com/。
}
}
},
}
}
然后请求内容如下:
export default {
methods: {
test() {
this.axios.get("/api/api/weather/city/101030100") // 相当于http://t.weather.sojson.com/api/weather/city/101030100
.then(res => {
console.log(res)
})
.catch(err => {
console.error(err);
})
}
},
}
最终成功拿到了数据
抽离配置
如果axios的配置少还好,如果配置内容多,全部写到main.js
还是有点恼火,所以我们可以模仿安装element-plus.js
的方法,给axios配置单独抽离到1个js文件里面,后面直接改这个配置文件即可。
axios.js
内容如下
import axios from "axios" // 引入
export default (app) => {
app.config.globalProperties.axios = axios // 将axios挂载到全局变量,后面可以通过 this.axios 调用
}
- 在
main.js
中引入
import installAxios from './plugins/axios'
installAxios(app)
后面要加什么全局配置、拦截器啥的,都直接在axios.js
里面➕就行
拦截器
可以结合上面的抽离配置一起用。有些时候要验证登陆,需要在header请求头加入自定义信息,如jwt-token,如果每一个axios发起请求的地方都去手动加一个header,那么肯定费时费力且不好维护,所以可以用到拦截器。
还有就是在响应的时候,如果要根据返回的message显示对应的内容、或者验证返回的状态码,都可以用拦截器;简而言之:axios请求前后所有重复的操作都可以抽象到拦截器中。
拦截器:在请求或响应被 then
或 catch
处理前拦截它们。
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});
- 1个例子(不要给所有的axios请求都带上token,最好限定一下源,不然万一开发途中有可控的URL,别人就可以抓取到token了)
import axios from "axios" // 引入
import { ElMessage } from 'element-plus'
import router from '../router'
import api from '@/config/api'
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
if(config.url.indexOf(api.frontUrl) != -1 ){ // 只有后端的URL才需要加token,避免token劫持
if (!config.headers['token']) {
config.headers['token'] = sessionStorage.token;
}
}
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
if(response.request.responseURL.indexOf(api.frontUrl) != -1 ) {
var resp = response.data
let message = resp.message
if (resp.code === 200) {
ElMessage({
message: message,
type: 'success',
duration: 1000,
})
} else {
ElMessage({
message: message,
type: 'error',
duration: 1000,
})
}
// 未登录
if (resp.code === 401) {
router.push({ path:'/login'})
}
}
return response;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});
export default (app) => {
app.config.globalProperties.axios = axios // 将axios挂载到全局变量,后面可以通过 this.axios 调用
}