axios的特性
- 支持Promise API
- 可以拦截请求和响应 ( 比如拦截授权信息等等 )
- 转换请求数据和响应数据 (加密解密敏感信息)
- 取消请求
- 自动转换JSON数据(一般http返回来的数据都是String类型,然后就要JSON.parse()做个手动转换,但是axios就会自动转换成json类型。)
- 客户端支持防御XSRF
可以用于前端(客户端、浏览器)和nodejs后端
axios在vue中的使用
-
npm i axios --save
-
在需要的页面上import axios from “axios”
-
使用:
axios.get('/data.json').then(data => { // 用的本地json文件 console.log(data.data.title) })
axios基础用法–get,post,put
axios请求方法: get,post, put, patch, delete
- get 获取数据
- post 提交数据(表单数据、文件 【图片、excel等】)
- put : 更新/编辑数据 (所有数据推送到后端)
- patch : 更新/编辑数据 (只有修改的 数据推送到后端)-
axios使用
create() {
// 直接用get方法
axios.get('/data.json', {
params: { // 如果发送GET请求需要携带参数
id: 12
}
}).then(res => console.log(res))
// 用axios的config对象
axios({
method: 'get',
url: '/data.json',
params: {
id: 12
}
}).then(res => {
console.log(res)
})
}
// 携带参数得到的最终url是 "http://localhost:8080/data.json?id=12"
Status Code: 200 // 访问正常 第一次访问
Status Code: 304 Not Modified // 不是第一次访问,数据没有修改,重定向,提高速度
post,put 方法
axios.post('url', {'请求数据'}, config) // 这是标准格式
// post 请求数据有两种形式:
// 1. application/json
let applicData = {
id: 12
}
axios.post('/post', applicData).then(res => console.log(res))
//或
axios({
url: '/post',
method: 'post',
data: applicData
}).then(res=>{console.log(res)})
// 2. form-data 表单提交(图片和文件上传)
let formData = new FormData()
for(let key in applicData){
formData.append(key, applicData[key])
}
axios.post('/post', formData).then(
res=>{
console.log(res)
}
)
浏览器F12-Network-post-Headers中:
Content-Type:application/json 或 multipart/form-data
delete 方法
axios.delete('/delete', {
params: { // id=12 直接放在url上 as Query String Parameters
id: 12
}
}).then(res => console.log(res))
axios.delete('/delete', {
data: { // url上不出现id=12, 在Headers中as Request Payload
id: 12
}
}).then(res => console.log(res))
并发请求 all,spread
同时进行多个请求,并统一处理返回值,比如 好友列表和用户信息分别从两个接口请求。
axios.all([ // all里面是一个请求的数组
axios.get('/data.json'),
axios.get('/city.json')
]).then(// then里面要用spread方法
axios.spread((dataRes, cityRes) => {
console.log(dataRes, cityRes)
})
)
创建axios实例
let instance = axios.create({
baseURL: "http://localhost:8080", // 请求域名 基本地址
timeout: 1000 // 超时时长设置 超过没response则401超时报错
})
instance.get('/data.json').then(res=>{
// /data.json是相对路径,发送请求时会自动拼接为baseURL+/data.json
console.log(res)
})
axios的基本配置参数
axios.create({
baseURL: "http://localhost:8080", // 请求域名 基本地址
timeout: 1000, // 超时时长设置 超过没response则401超时报错
url: '/data.json', // 请求路径
method: 'post', // 请求方法
header: {token}, // 请求头
params:{}, // 请求参数 -- 拼接在url中
data:{} // 请求参数--放在请求体中
})
axios配置类别
- 全局配置(优先级最低)-- 实际开发中很少用到
axios.defaults.timeout = 2000
axios.defaults.baseURL = 'http://localhost:8081'
全剧配置一般只配置这两个参数
- 实例配置(优先级中间)
let instance = axios.create();
instance.defaults.timeout = 2000; // 修改实例配置
- 请求配置(优先级最高)
instance.get('/data', {
timeout: 2000
})
axios进阶方法-- 实例、配置、拦截器、取消请求
拦截器
在请求或响应在被处理前拦截它们 – 发起请求前和后端响应之后做一些处理
分为请求拦截器和响应拦截器
拦截器通常会给axios的实例设置,而不是全局axios设置,否则容易造成全局污染
// 请求拦截器
axios.interceptors.request.use(
config => { // 第一个回调函数是配置函数
// 在发送请求前需要做些什么 -- 修改配置或弹出内容等
return config // 要记得返回设置好的config
}, err=>{ // 第二个回调函数是错误函数
// 在请求错误的时候做些什么
return Promise.reject(err) // err会到axios.get().then(成功).catch(err)
}
)
// 响应拦截器
axios.interceptors.response.use(
res=> { // 第一个回调函数
// 在请求成功对响应数据的处理
return res
}, err=>{ // 第二个回调函数
// 响应错误做些什么
return Promise.reject(err)
}
)
// 取消拦截器 -- 不常用
let interceptors = axios.interceptors.request.use(config=>{
config.headers={
auth: true
}
return config
})
axios.interceptors.request.eject(interceptors)
// 实际例子 登陆状态 -- 后台返回token:‘’来判断权限,通常会放到header中
let instance = axios.create({})
instance.interceptors.request.use(
config=>{
config.headers.token = '' // 给header加token用来访问需要登陆的接口
return config
}
)
let instanceNotoken = axios.create({}) // 不加拦截器可以用来访问不需要登陆的接口
// 移动端开发 -- 注重用户体验,可以在请求的时候添加个等待的画面
let instance_phone = axios.create({})
instance_phone.interceptors.request.use(config=>{
$('#modal').show() // 发送请求的时候显示弹窗
return config
})
instance_phone.interceptors.response.use(res=>{
$('#modal').hide() // 请求成功后隐藏弹窗
return res
})
错误处理
请求发生错误时进行的处理 // 404接口未找到,401请求超时
axios.get(url)
.then() // 请求成功
.catch(err=>{ // 请求或响应失败的err都会进入到catch中
//在实际开发过程中,一般需要添加统一错误处理,而不是添加catch,否则每个接口一个catch会比较不好处理
})
// 统一添加错误处理
let instanceErr = axios.create({});
instanceErr.interceptors.request.use(
config=>{
//
return config
},err => {
//请求错误 一般http状态码以4开头 401、 404
return Promise.reject(err)
}
)
instanceErr.interceptors.response.use(
res=>{
//
return res
},err => {
//响应错误 一般http状态码以5开头500系统错误,502系统重启
$('#modal').show()
setTimeout(() => {
$('#modal').hide()
}, 2000)
return Promise.reject(err)
}
)
instanceErr.get('/data.json')
.then(res=>{...})
.catch(err=>{ // 如果是正常处理err,就不需要添加catch了,会用上面统一的err处理方式--modal展示和隐藏
// But 如果这个接口的错误需要单独处理,就可以添加catch再重新写处理方式
})
在实际开发过程中,一般需要添加统一错误处理,而不是添加catch,否则每个接口一个catch会比较不好处理
取消请求
取消正在进行的http请求 – 用的很少
let source = axios.CancelToken.source();
axios.get('/data.json', { // 声明了一个带有取消请求token的请求
cancelToken: source.token
}).then(res=>{
console.log(res)
}).catch(err=>{console.log(err)})
// 发起请求后,取消请求:
source.cancel('cancel http') // message可不用
用到取消请求的情况:大型商城返回结果要 3-5秒,用户在此期间查询了下一类,上一个请求就用不到了,就可以取消请求
axios实际开发例子
获取通讯录列表,编辑、新增
在后端接口的文件夹中打开power shell,
npm i
node index.js //启动服务
安装vant plugin: npm i babel-plugin-import -D
axios进一步封装,在项目中的实际应用(比如授权信息放到header里进一步封装)
- 比如每一个请求都有一个catch,Toast… 造成代码冗余
- 带参数的请求,会造成每个请求的格式都不统一
- 请求的url每个都不同,不好管理–>放到统一的json文件中,请求的时候统一调用
// 第一步 封装每个页面中用到的请求到一个常量中
>>>src/service/contactApi.js // 封装请求url和方式
const CONTACT_API = {
// 获取联系人列表
getContactList: {
method: 'get',
url: '/contactList'
}
}
export default CONTACT_API // 要记得export,因为别的地方要引入
// 第二步 封装请求方式到一个函数中-- 统一请求方式
>>>src/service/http.js
>import axios from 'axios'
import service from './contactApi'
import { Toast } from 'vant'
// service 循环遍历,输出不同的请求方法
let instance = axios.create({
baseURL: 'http://localhost:9000/api',
timeout: 1000
})
const Http = {}; // 包裹请求方法的容器
for (let key in service) {
let api = service[key]; // 遍历的每个请求的url, method
Http[key] = async (params, isFormdata=false, config={}) => { // 给形参设置初始值
let url = api.url;
let newParams = {};
// 判断是否为form-data
if(params && isFormdata) { // 如果有参数,并且是formData类型,则要把参数转换成formData类型
newParams = new FormData();
for(let k in params){
newParams.append(k, params[k]); // append()方法是FormData数据类型添加内容的方法
}
}else { // 如果不是formData类型,就直接复制
newParams = params;
}
// 不同请求的判断
let response = {}; // 每个请求都需要一个返回值
if(api.method === 'post' || api.method === 'put' || api.method === 'patch') {
try{
response = await instance[api.method](url, newParams, config);
}catch(err){
response = err;
}
}else if(api.method === 'delete' || api.method === 'get') {
config.params = newParams;
try{
response = await instance[api.method](url, config);
}catch(err){
response = err;
}
}
return response // 函数的最终的响应返回值
}
}
// 拦截器
instance.interceptors.request.use(// 请求拦截器
config => {
// 请求前的操作
Toast.loading({
mask: false,
duration: 0, // 默认是1,设为0是一直存在
forbidClick: true, // 禁止点击
message: 'Loading...'
});
return config
}, err => {
//请求错误
Toast.clear(); // 把一直存在的loading去掉
Toast('error')
}
)
instance.interceptors.response.use(// 响应拦截器
res => {
// 请求成功
Toast.clear(); // 请求成功先吧loading去掉
return res.data // res里包含了很多东西,我们只用data(code...)
}, err => {
Toast.clear();
Toast("响应错误...")
}
)
export default Http
// 第三步 把Http挂载到Vue实例上
>>> main.js
import Http from './service/http'
Vue.prototype.$Http = Http // 就可以全局使用了,不需要每个页面都引入
// 第四步 页面上使用Http
>>> ContactList.vue
async onDelete (info) { // 删除联系人
let res = await this.$Http.delContactList(info);
if(res.code === 200){
Toast('删除成功'),
this.showEdit = false;
this.getList();
}
}
网络课程: https://www.imooc.com/learn/1152