Axios 是一个基于 promise 的 HTTP 库,可以用于在游览器和nodejs环境中进行请求网站资源。
有以下特性:
从浏览器中创建 XMLHttpRequests
从 node.js 创建 http 请求
拦截请求和响应
转换请求数据和响应数据
取消请求
自动转换JSON 数据
客户端防范XSRF
一般在项目的src目录中,新建一个api文件夹,然后在里面新建一个http.js、request.js和一个api.js文件。http.js文件用来封装我们的axios,request.js用来封装请求方法,api.js用来统一管理我们的接口。
import axios from 'axios' // 在http.js中引入axios
export default axios // 自定义导出
利用node环境变量来作判断,用来区分开发、测试、生产环境
// 环境的切换
if (process.env.NODE_ENV == 'development') {
axios.defaults.baseURL = 'http://127.0.0.1:3000';
} else if (process.env.NODE_ENV == 'test') {
axios.defaults.baseURL = 'http://192.168.0.185:8080';
} else if (process.env.NODE_ENV == 'production') {
axios.defaults.baseURL = 'http://api.123.com/';
}
// 或者
switch (process.env.NODE_ENV) {
case "production":
axios.defaults.baseURL = "http://api.123.com/";
break;
case "test":
axios.defaults.baseURL = "http://192.168.0.185:8080";
break;
default:
axios.defaults.baseURL = "http://127.0.0.1:3000";
}
对应 package.json的增加:
{
"script": {
"serve:test": "set NODE_ENV=test$$vue-cli-service serve",
"serve:production": "set NODE_ENV=production$$vue-cli-service serve",
}
}
通过axios.defaults.timeout设置默认的请求超时时间。例如超过了10s,就会告知用户当前请求超时,请刷新等。
axios.defaults.timeout = 10000;
axios.defaults.withCredentials = true // 设置跨域是否允许携带凭证
axios.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
axios.interceptors.request.use(
config => {
// 每次发送请求之前判断vuex中是否存在token
// 如果存在,则统一在http请求的header都加上token,这样后台根据token判断你的登录情况
// 即使本地存在token,也有可能token是过期的,所以在响应拦截器中要对返回状态进行判断
// const token = store.state.token;
let token = sessionStorage.getItem('token')
token && (config.headers.Authorization = token);
return config;
},
error => {
return Promise.reject(error);
})
// 具体的拦截器逻辑以具体业务为准
注意:
每次发起请求之前需要获取token,token可以用sessionStorage或localStorage存在本地,也可以在vuex中获取token
如果有token,将token保存在请求的header上,发送给后台验证
响应拦截器可以在接收到响应后先做一层操作,如根据状态码判断登录状态、授权
// 响应拦截器
axios.interceptors.response.use(
response => {
return response
},
error => {
let {response} = error;
if (response) {
// 服务器最起码有返回结果
switch (response.status) {
// 401: 未登录
// 未登录则跳转登录页面,并携带当前页面的路径
// 在登录成功后返回当前页面,这一步需要在登录页操作。
case 401:
router.replace({
path: '/login',
query: { redirect: router.currentRoute.fullPath }
});
break;
// 403 token过期
// 登录过期对用户进行提示
// 清除本地token和清空vuex中token对象
// 跳转登录页面
case 403:
alert('登录过期');
// 跳转登录页面,并将要浏览的页面fullPath传过去,登录成功后跳转需要访问的页面
setTimeout(() => {
router.replace({
path: '/login',
query: {
redirect: router.currentRoute.fullPath
}
});
}, 1000);
break;
case 404:
console.log('找不到页面');
break;
}
} else {
// 服务器连结果都没有返回
if (!window.navigator.onLine) {
// 断网处理,可以跳转到断网页面
return;
}
return Promise.reject(error)
}
}
)
// 具体的拦截器逻辑以具体业务为准
这里我再创建一个request.js,这里面放的是具体请求。
import axios from './http.js'
/**
* get方法,对应get请求
* @param {String} url [请求的url地址]
* @param {Object} params [请求时携带的参数]
*/
export function get(url, params){
return new Promise((resolve, reject) =>{
axios.get(url, {
params: params
})
.then(res => {
resolve(res.data);
})
.catch(err => {
reject(err.data)
})
});
}
/**
* post方法,对应post请求
* @param {String} url [请求的url地址]
* @param {Object} params [请求时携带的参数]
*/
export function post(url, params) {
return new Promise((resolve, reject) => {
axios.post(url, JSON.stringify(params))
.then(res => {
resolve(res.data);
})
.catch(err => {
reject(err.data)
})
});
}
/**
* put方法,对应put请求
* @param {String} url [请求的url地址]
* @param {Object} params [请求时携带的参数]
*/
export function put(url, param) {
return new Promise((resolve, reject) => {
axios.put(url, param)
.then(res => {
if (res.data.Code === 200) {
resolve(res.data)
} else {
reject(res.data)
}
}).catch(err => {
reject(err)
})
})
}
/**
* del方法,对应del请求
* @param {String} url [请求的url地址]
* @param {Object} params [请求时携带的参数]
*/
export function del(url, param {
return new Promise((resolve, reject) => {
axios.delete(url, {
params: param
}).then(res => {
if (res.data.Code === 200) {
resolve(res.data)
} else {
reject(res.data)
}
}).catch(err => {
reject(err)
})
})
创建api.js用来统一管理我们的接口
import { get, post } from './request.js'
//请求地址api
const apiAddress = query => post('/api/v1/'address, query);
//请求列表api
const apiList = query => post('/api/v1/list', query);
。。。。。
export default {apiAddress,apiList}
在组件中调用
import { apiAddress,apiList } from '@/api/api';// 导入我们的api接口
export default {
name: 'Address',
created () {
this.onLoad();
},
methods: {
// 获取数据
onLoad() {
// 调用api接口,并且提供了两个参数
apiAddress({
type: 0,
sort: 1
}).then(res => {
// 获取数据成功后的其他操作
………………
})
}
}
}
在全局main.js的调用,在main.js中引入http.js、api.js,挂在vue原型上
import Vue from 'vue'
import axios from './api/http/
import {get, post, put, del} from './request'
import api from '.api/api'
Vue.prototype.$get = foreach;
Vue.prototype.$post = post
Vue.prototype.$put = put
Vue.prototype.$delete = del
Vue.prototype.$api = api