Axios在Vue中的使用
1.Axios基础用法:
1.1.axios请求方法:
请求方式具体是由后端定义的,请求的接口都是请求到后端,再由后端对数据进行操作
- get请求:
- 用于从后端获取数据
- axios.get()只有两个参数
- get方法在Vue中的两种写法:(下面的代码包含在vue的组件里)
<script> import axios from 'axios' export default { name: 'axios2-2', created () { /*带有params参数(可以不带params参数)后在访问时对应的请求路径就是 http://localhost:8080/static/data.json?id=12 */ axios.get('../static/data.json',{ params:{ id:12 } }).then((res) => { console.log(res) }) axios({ method: 'get', url: '../static/data.json', params:{ id:12 } }).then((res) => { console.log(res) }) } } </script>
- post请求:(一般用于新建)
- 用于向后端提交数据(包括表单提交以及文件上传<上传图片、json文件等等>)
- axios.post()方法有三个参数,第一个是路径,第二个是请求的数据,第三个是config。
- 请求数据的格式有两种:
- form-data:用于表单提交(图片上传、文件上传)
- application/json:大多数情况下都用这个,对前后端比较友好
- 在vue中的代码写法(两种)post:
let data = { id: 12 } //data代表要提交的数据 axios.post('/post', data).then(res => { console.log(res) }) axios({ method: 'post', url: '/post', data: data }).then(res => { console.log(res) })
- form-data格式的请求:(但请求的类型是application/json)
let formData = new FormData() for (let key in data) { formData.append(key, data[key]) } axios.post('/post', formData).then(res => { console.log(res) })
- put请求:(一般用于更新)
- 用于编辑/更新数据(将所有的数据全部推送到后端,再由后端将数据更新到数据库中)
- axios.put()方法有三个参数,第一个是路径,第二个是请求的数据,第三个是config。
- 在vue中的代码写法put:
另一种方法同上同理axios.put('/put',data).then(res=>{ console.log(res) })
- patch请求:
- 用于编辑/更新数据(只将修改的数据推送到后端)
- axios.patch()方法有三个参数,第一个是路径,第二个是请求的数据,第三个是config。
- 在vue中的代码写法patch:
axios.patch('/patch',data).then(res=>{ console.log(res) })
- delete请求:
- 用于删除数据,调用的时候要与后端沟通清楚删除接口如何调用
- axios.delete()只有两个参数,与get请求类似
- 在vue中的代码写法delete:
axios.delete('/delete',{ params:{ id:12 } }).then(res=>{ console.log(res) }) //将params改为data,就不是在url中进行传输的了 axios.delete('/delete', { data: { id: 12 } }).then(res => { console.log(res) }) //另一种写法 axios({ method: 'delete', url: '/delete', params: {}, data: {} }).then(res => { console.log(res) })
1.2.并发请求
并发请求:同时进行多个请求,并统一处理返回值
两个方法:
- axios.all():
- 参数是一个数组,数组里面是一个一个axios请求
- Axis.spread():
- 在axios.all()的多个请求完成后,把返回数据进行分割后再进行统一的处理
- 在vue中的写法:
axios.all([ axios.get('../static/data.json'), axios.get('../static/city.json') ]).then( //spread中参数的个数取决于all方法中有几个参数 axios.spread((dataRes, cityRes) => { //这儿可以对返回的数据进行一系列处理,这儿只是简单的输出 console.log(dataRes,cityRes) }) )
2.axios方法深入:
2.1.创建axios实例
后端接口地址有多个,并且超时时长不一样。axios实例可以在实例中配置参数,用实例去请求,更加方便。
<script>
import axios from 'axios'
export default {
name: 'axios3-1',
components: {
},
created () {
// eslint-disable-next-line no-unused-vars
// create的参数是axios的配置信息
let instance = axios.create({
baseURL: 'http://localhost:8080',
timeout: 1000 // 设置超时时长(1s),如果后端长时间没有返回数据,接口就会报超时。状态码:401
})
instance.get('../static/data.json').then(res => {
console.log(res)
})
}
}
</script>
- 上述代码就是axios实例的创建,instance就是实例(类比java类实例的创建)
- 在项目很简单的时候可以不用创建实例,直接使用axios
2.2.axios实例的相关配置
2.2.1.axios常用参数
即axios.create()方法里的参数,也可以是axios.get()的config
- baseURL:请求的域名/基本地址
baseURL的值和axios.get方法里的参数连接起来就是请求的路径:http://localhost:8080/static/data.jsonlet instance = axios.create({ baseURL: 'http://localhost:8080', }) instance.get('../static/data.json').then(res => { console.log(res) })
- timeout:请求的超时时长,单位是ms,默认1000ms(即1s)。如果请求的数据量较大,后端的处理时间较长,一旦超过该时间,后端就会返回401,代表超时。
- url:请求的路径
let instance = axios.create({ baseURL: 'http://localhost:8080', url:'../static/data.json' //请求路径 }) instance.get('../static/data.json').then(res => { console.log(res) })
- method:请求方法(get, post,put,patch,delete)
- headers:{} 设置请求头,可以在请求头里添加一些参数
let instance = axios.create({ baseURL: 'http://localhost:8080', headers:{ token:'' //用token识别当前登陆人的身份信息,将token传给后端 } }) instance.get('../static/data.json').then(res => { console.log(res) })
- params:{} 将请求参数拼接在url上
- data:{} 将请求参数放在请求体里
2.2.2.axios配置的地方
优先级:请求配置>实例配置>全局配置
- axios全局配置:(一般就修改以下两个)
axios.defaults.timeout=1000 axios.defaults.baseURL='http://localhost:8080'
- axios实例配置
let instance = axios.create() //创建完实例后进行修改 instance.defaults.timeout=3000
- axios请求配置
instance.get('/data.json',{ timeout=5000 })
3.拦截器
在请求或响应被处理前拦截它们,即在发起请求之前做处理以及后端响应之后做一些处理
- 请求拦截器
请求错误是指发送请求没有成功到达后端export default { name: 'axios3-3', components: { }, created () { axios.interceptors.request.use( config => { // 在发送请求前做些什么 return config },err=>{ //在请求错误的时候做些什么 return Promise.reject(err) }) } }
- 响应拦截器
响应错误是指请求已经到后端,后端返回错误信息axios.interceptors.response.use( res => { // 请求成功对响应数据做处理 return res }, // axios.get().then(res=>{}),响应的数据会到这儿,可以对数据进行操作 err=>{ //响应错误做些什么 return Promise.reject(err) })
- 取消拦截器(一般不用)
let interceptors = axios.interceptors.request.use (config => { config.headers = { auth: true } return config }) axios.interceptors.request.eject(interceptors)
- 实例
在请求的时候显示弹窗,在响应后隐藏弹窗let instance = axios.create({}) instance.interceptors.request.use(config => { $('modal').show() return config }) instance.interceptors.response.use(res => { $('modal').hidden() return res })
4.错误处理
在请求错误时进行的处理
无论是请求错误还是响应错误,最后都会进入axios.get()的catch进行错误处理。在实际开发过程中,一般要添加统一的错误处理
import axios from 'axios'
export default {
name: 'axios3-4',
components: {
},
created () {
axios.interceptors.request.use(
config => {
return config
}, err => {
//请求错误处理 一般http状态码以4开头,常见:401超时 404not found
$('modal').show()
setTimeout(()=>{
$('modal').hide()
},2000) //先展示错误,过2s将其隐藏
return Promise.reject(err)
})
axios.interceptors.response.use(
res => {
return res
},
err => {
//响应错误处理 一般http状态码以5开头,常见:500系统错误 502系统重启
$('modal').show()
setTimeout(()=>{
$('modal').hide()
},2000) //先展示错误,过2s将其隐藏
return Promise.reject(err)
})
axios.get('../static/data.json').then(res => {
console.log(res)
}).catch(err=>{
//进一步进行错误处理的操作可以写在这儿
console.log(err)
})
}
}
5.取消请求
取消正在进行的http请求(稍做了解,在实际项目中不多用)
let source = axios.CancelToken.source()
axios.get('../static/data.json', {
cancelToken: source.token
}).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
//取消请求
source.cancel('cancel http')
6.axios实战例子:
6.1.项目配置:
- vue组件库vant安装:
- 网址:https://youzan.github.io/vant/#/zh-CN/
- 后端请求的接口服务的运行:
- 将下载下来的接口服务放在项目文件夹下(本电脑路径:/Users/taozehua/Downloads/软工2/vue学习/axios学习/axios_node_api-master)
- 接口文档存放的是接口说明
- 用终端打开该文件夹,运行
- cnpm install 安装依赖
- node index.js 启动后端服务
- 将下载下来的接口服务放在项目文件夹下(本电脑路径:/Users/taozehua/Downloads/软工2/vue学习/axios学习/axios_node_api-master)
6.2.代码解析
<template>
<div class="home">
<!--从vant引入联系人列表-->
<van-contact-list
id="van-contact-list_add"
:list="list"
default-tag-text="默认"
@add="onAdd"
@edit="onEdit"
/>
// showEdit编辑弹窗的显示
<van-popup v-model="showEdit" position="bottom" id="van-popup">
<van-contact-edit
:contact-info="editingContact" // 正在编辑的联系人数据
:is-edit="isEdit" //是否在编辑,记录状态
@save="onSave"
@delete="onDelete"
/>
</van-popup>
</div>
</template>
<script>
//引入vant组件和axios
import {ContactList, Toast,ContactEdit, Popup} from 'vant'
import axios from 'axios'
export default {
name: 'contactList',
components: {
//注册要用到的vant组件,只有注册后才能显示在网页上
//Toast组件不需要注册,只有在template中用到的组件才要注册
[ContactList.name]: ContactList,
[ContactEdit.name]: ContactEdit
[Popup.name]: Popup
},
data () {
return {
list: [], // 联系人列表
instance: null, // axios实例
showEdit: false, // 编辑弹窗的显示
editingContact: {}, // 正在编辑的联系人数据
isEdit: false
}
},
methods: {
// 添加联系人
onAdd () {
this.showEdit = true
this.isEdit = false
},
// 编辑联系人
onEdit (info) {
this.showEdit = true
this.isEdit = true
this.editingContact = info //将内容添加到正在编辑的联系人的数据中
},
// 保存联系人
onSave () {
if (this.isEdit) {
// 编辑保存
// 接口文档里的/contact/edit有三个参数:id,name,tel
// 这三个参数不需要单独获取,已经存在了info中
// 编辑用put
this.instance.put('/contact/edit', info).then(
res => {
if (res.data.code === 200) {
Toast('编辑成功')
this.showEdit = false // 关闭弹窗
this.getList()
}
}).catch(() => {
Toast('编辑失败')
})
} else {
// 新建保存,将结果存到接口文档里的/contact/new/json中,用post向后端发送数据
this.instance.post('/contact/new/json', info).then(res => {
//检查返回的状态,200代表成功
if (res.data.code === 200) {
Toast('新建成功')
this.showEdit = false // 关闭弹窗
//新建后需要进行更新联系人列表,即重新获取联系人列表
this.getList()
}
}).catch(() => {
Toast('新建失败')
})
}
},
// 删除联系人
onDelete (info) {
this.instance.delete('/contact',{
//将id拼接在url上,查询接口文档,删除的参数只有id,且要将id拼接在url上
params:{
id:info.id
}
}).then(
res=>{
if (res.data.code === 200) {
Toast('删除成功')
this.showEdit = false // 删除成功后关闭弹窗
this.getList()
}
}).catch(() => {
Toast('删除失败')
})
},
//获取联系人列表
getList(){
//从后端获取数据,get参数对应的是接口文档里的url中的一个
this.instance.get('/contactList').then(res => {
//res是后端返回的数据,可以先使用consle.log(res)在浏览器中查看返回数据的格式
//再去取用数据
this.list = res.data.data
// eslint-disable-next-line handle-callback-err
}).catch(err => {
//使用vant的Toast轻提示组件输出错误信息
Toast('请求失败,请稍后重试')
})
}
},
created () {
//创建axios实例
this.instance = axios.create({
//baseURL对应接口文档里的后端接口地址
baseURL: 'http://localhost:9000/api',
timeout: 1000
})
//从后端获取联系人列表
this.getList()
}
}
</script>
<style scoped>
.van-contact-list_add{
z-index: 0;
}
<!--将弹窗铺满-->
.van-popup{
height: 100%;
}
</style>
7.axios进一步封装
将所有的url放在一个js文件中
代码见axios实例中的service文件夹
创建url统一的管理文件时,需要按照模块进行划分。eg:联系人列表、订单列表等不同的业务模块要封装到不同的js文件中
Eg:
- 在项目中新建一个service文件夹,在该文件夹下创建一个js文件,将接口文档中给出的url和method对应写入文件。最后再用export default CONTACT_API将创建的api对象导入出去,方便在别的地方引用。
const CONTACT_API = { // 获取联系人列表 getContactList: { method: 'get', url: '/contactList' }, // 新建联系人 form-data newContactForm: { method: 'post', url: '/contact/new/form' }, // 新建联系人 appilcation/json newContactJson: { method: 'post', url: '/contact/new/json' }, // 编辑联系人 editContact: { method: 'put', url: '/contact/edit' }, // 删除联系人 delContact: { method: 'delete', url: '/contact' } } // 将创建的api对象导入出去,方便引用 export default CONTACT_API
- 对axios进行封装,完成请求格式和参数的统一。在service文件夹下创建http.js文件,用于对axios进行进一步封装
完成代码:// 对axios进行封装 import axios from 'axios' import service from './contactApi' // 将service循环遍历输出不同的请求方法 let instance = axios.create({ baseURL: 'http://localhost:9000/api', timeout: 1000 }) // 包裹请求方法的容器 const Http = {} for (let key in service) { // api中存放有url和method let api = service[key] // async function()的作用是避免进入回调地狱 Http[key] = async function ( params, // 请求参数get:url,put,post,patch(data),delete:url isFormData = false, // 标识是否是form-data请求 config = {} // 配置参数 ) { let res = null try { // res对应于 // axios.get().then(res=>{ // // }).catch(err=>{ // // })中的res res = await axios.get('url') } catch (err) { // 捕捉错误 // 对应于 // axios.get().then(res=>{ // }).catch(err=>{ // // })中的catch部分err res = err } } }
// 对axios进行封装 import axios from 'axios' import service from './contactApi' // 将service循环遍历输出不同的请求方法 let instance = axios.create({ baseURL: 'http://localhost:9000/api', timeout: 1000 }) // 包裹请求方法的容器 const Http = {} // 请求格式/参数的统一 for (let key in service) { // api中存放有url和method let api = service[key] // async function()的作用是避免进入回调地狱 Http[key] = async function ( params, // 请求参数get:url,put,post,patch(data),delete:url isFormData = false, // 标识是否是form-data请求 config = {} // 配置参数 ) { let newParams = {} // content-type是否是form-data的判断 // 如果是form-data格式,要new一个FormData的对象 if (params && isFormData) { newParams = new FormData() for (let i in params) { newParams.append(i, params[i]) } } // 如果是application/json格式 else { // 直接赋值即可 newParams = params } // 不同请求的判断 let response = {} // 请求的返回值 if (api.method === 'put' || api.method === 'post' || api.method === 'patch') { // 这三种方法请求相同 try { response = await instance //newParams就相当于data,只不过换了个格式 await instance[api.method](api.url, newParams, config) } catch (err) { response = err } } else if (api.method === 'delete' || api.method === 'get') { // delete 和 get没有第二个参数 config.params = newParams try { response = await instance await instance[api.method](api.url, config) } catch (err) { response = err } } return response } }
- 加上请求拦截器
// 拦截器的添加 // 请求拦截器 instance.interceptors.request.use(config => { // 发起请求前做些什么 // Toast.loading会在页面中出现等待的图标 Toast.loading({ mask: false, duration: 0, // 一直存在 forbidClick: true, // 禁止点击 message: '加载中……' }) return config }, () => { // 请求错误 Toast.clear() Toast('请求错误') }) // 响应拦截器 instance.interceptors.response.use(res => { // 请求成功 Toast.clear() return res.data }, () => { // 请求错误 Toast.clear() Toast('请求错误') }) export default Http
- 调用,在main.js中引入Http,全局都可以调用
import Http from "../service/http" //把http挂在到vue实例上 Vue.prototype.$Http=Http
- 验证