这是我第8篇简书。
这篇文章去年5月就写了,还差一点没收尾,觉得写的不好放在日记本里没发布,今天就发了吧,重点看我axios的那个长长的例子。初学者如果看不懂私信我吧。。有错误也请大佬拍砖,毕竟我已经心不在焉的去考公了,做项目只想完成功能就算了,心不在这里啊。。。
vue-resource
早已不再更新!尤大大推荐用axios!!
这里还是先简单说一下vue-resource。
vue-resource是Vue.js的一款插件,它可以通过XMLHttpRequest或JSONP发起请求并处理响应。也就是说,Ajax能做的事情,vue-resource插件一样也能做到,而且vue-resource的API更为简洁。划重点,vue-resource还提供了非常有用的inteceptor(拦截器)功能(经常使用),使用inteceptor可以在请求发送前和发送请求后做一些处理,比如使用inteceptor在ajax请求时显示loading界面,或者在请求发送前在headers中设置token,加入token验证,拦截器在axios中详细介绍。
一、简单介绍vue-resource用法
1.引入
import Vue from 'vue'
import VueResource from 'vue-resource'
Vue.use(VueResource)
2.使用
引入vue-resource后,可以基于全局的Vue对象使用http,也可以基于某个Vue实例使用http。
在一个Vue实例内使用$http
this.$http.get('/Url', [options]).then((response) => {
// 响应成功回调
}, (response) => {
// 响应错误回调
});
3.跨域
解决vue-resource post请求跨域问题:
vue提供了一个简单的解决方法,就是 Vue.http.options.emulateJSON = true
其实等同于在headers中添加 'Content-Type': 'application/x-www-form-urlencoded'。
注意:$http请求和jquery中使用ajax还是有点区别,这里的post的data默认不是以form data
的形式,而是request payload
。所以你们别忘了将emulateJSON 属性设置为true,即可解决这个问题。Vue.http.options.emulateJSON = true
form data和request payload的区别:
- form date
get请求,是将请求参数以&方法,拼接在url后面,如:http://www.dxl.com?name=dxl&password=8888;
真正可以明显看出区分的是在post请求上,
post请求时,头文件 中Content-Type 是默认值 application/x-www-form-urlencoded,参数是放在form date
中的。 - request payload
post请求时,头文件 中Content-Type 是默认值 application/json;charset=UTF-8,参数是放在request payload
中的。
JSONP请求:
getJsonp: function() {
this.$http.jsonp(this.apiUrl).then(function(response){
this.$set('gridData', response.data)
})
}
4.resource服务
vue-resource
提供了另外一种方式访问HTTP——resource服务
resource对象也有两种访问方式:
全局访问:Vue.resource
实例访问:this.$resource
(1)get请求
getCustomers: function() {
var resource = this.$resource(this.apiUrl)
vm = this
resource.get()
.then((response) => {
vm.$set('gridData', response.data)
})
.catch(function(response) {
console.log(response)
})
}
(2)post请求
使用save方法发送POST请求。
createCustomer: function() {
var resource = this.$resource(this.apiUrl)
vm = this
resource.save(vm.apiUrl, vm.item)
.then((response) => {
vm.$set('item', {})
vm.getCustomers()
})
this.show = false
}
(3)使用update方法发送PUT请求,使用remove或delete方法发送DELETE请求
5.拦截器interceptors
Vue.http.interceptors.push((request, next) => {
// ...
// 请求发送前的处理逻辑
// ...
next((response) => {
// ...
// 请求发送后的处理逻辑
// ...
// 根据请求的状态,response参数会返回给successCallback或errorCallback
return response
})
})
二、axios
1.介绍
Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。
看这个吧,传送门→https://www.kancloud.cn/yunye/axios/234845
axios支持IE8。
它可以:
- 从浏览器中创建
XMLHttpRequests
- 从 node.js 创建
http
请求 - 支持 Promise API
- 拦截请求和响应
- 转换请求数据和响应数据
- 取消请求
- 自动转换 JSON 数据
- 客户端支持防御
XSRF
(1)get请求
axios.get('/user', {
params: {
ID: 1111
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
// 还可以这么写,es7新特性async/await
async function getUser() {
try {
const response = await axios.get('/user?ID=1111');
console.log(response);
} catch (error) {
console.error(error);
}
}
*async用于声明一个函数是异步的,而await是“等待”的意思,就是用于等待异步完成。
await只能在async函数中使用。
await可以让js进行等待,直到一个promise执行并返回它的结果,js才会继续往下执行。
async/await 面试经常问到哦,百度查一下,划重点
(2)post请求
axios.post('/user', {
firstName: 'xiliDong',
lastName: 'dongxili'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
//或者这样写
axios({
method: 'post',
url: '/user',
data: {
firstName: 'xiliDong',
lastName: 'dongxili'
}
});
(3)执行多个并发请求
function getUserAccount() {
return axios.get('/user/12345');
}
function getUserPermissions() {
return axios.get('/user/12345/permissions');
}
axios.all([getUserAccount(), getUserPermissions()])
.then(axios.spread(function (acct, perms) {
// 两个请求现在都执行完成
}));
2.创建实例(重点)
可以使用自定义配置新建一个 axios 实例
axios.create([config])
var instance = axios.create({
baseURL: 'https://some-domain.com/api/',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'}
});
(1)响应结构:
{
data: {}, // data由服务器提供的响应
status: 200, // 服务器响应的 HTTP 状态码
statusText: 'OK', // 服务器响应的 HTTP 状态信息
headers: {}, // 服务器响应的头
config: {} // 为请求提供的配置信息
}
使用 then 时,你将接收下面这样的响应:
axios.get('/user/1111')
.then(function(response) {
console.log(response.data);
console.log(response.status);
console.log(response.statusText);
console.log(response.headers);
console.log(response.config);
});
(2)指定配置的默认值:
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
- 自定义实例默认值:
// 创建实例时设置配置的默认值
var instance = axios.create({
baseURL: 'https://api.example.com'
});
// 在实例已创建后修改默认值
instance.defaults.headers.common['Authorization'] = AUTH_TOKEN;
(3)拦截器:
(axios配置看我这个例子就差不多了)
// request拦截器
import axios from 'axios'
import router from '../router'
// 创建axios实例
const service = axios.create({
timeout: null // 请求超时时间
})
let serviceTips = '服务器超时'
// request拦截器
service.interceptors.request.use(
config => {
// console.log(service.interceptors)
// 获取本地token
let token = localStorage.getItem('tokendata')
// 设置请求头
let headers = 'application/json'
// 是否携带token
let tokenFlag = true
// 是否修改请求信息
if (config.opts) {
// 获取携带token状态
tokenFlag = config.opts ? config.opts.token : true
// 获取请求头
headers = config.opts.Header ? config.opts.Header : 'application/json'
// 拓展头部参数
let Head = config.opts.Head
if (Head) {
for (let key in Head) {
config.headers[key] = Head[key]
}
}
}
// 暂时不加入token验证
// if (token && tokenFlag) {
// // 条件允许,携带token请求
// config.headers['JSESSIONID'] = token
// // config.headers['X-Auth0-Token'] = token
// } else {
// headers = 'application/x-www-form-urlencoded'
// }
// 设置请求格式
config.headers['Content-Type'] = headers
return config
},
err => {
return Promise.reject(err)
}
)
// http response 服务器响应拦截器
service.interceptors.response.use(
response => {
return response
},
error => {
if (error.response) {
switch (error.response.status) {
case 401:
error.response.data = '登陆超时,重新登陆'
router.replace({
path: '/login',
query: {
redirect: router.currentRoute.fullPath
} // 登录成功后跳入浏览的当前页面
})
break
case 404:
error.response.data = '资源不存在'
break
case 406:
error.response.data = '头部无携带token'
break
case 412:
// 拦截错误 并重新跳入登页重新获取token
router.replace({
path: '/login',
query: {
redirect: router.currentRoute.fullPath
} // 登录成功后跳入浏览的当前页面
})
error.response.data = '秘钥失效'
localStorage.removeItem('tokendata') // 清除token
break
case 415:
error.response.data = '请求type有误'
break
case 500:
error.response.data = '服务器异常'
break
}
serviceTips = error.response.data
}
Message.error(serviceTips)
return Promise.reject(serviceTips)
}
)
export default service
配置好了怎么使用呢?
在api.js中引入拦截器:
import fetch from '@/utils/fetch' // 拦截器
export function getList(obj) {
const data = obj
return fetch({
url: '',
method: 'POST',
data
})
}
--------------------------------
可以使用 validateStatus 配置选项定义一个自定义 HTTP 状态码的错误范围。
export function getList(obj) {
const data = obj
return fetch({
url: '',
method: 'POST',
validateStatus: function(status) {
// return status >= 200 && status < 300; // 默认的
return status < 500; // 状态码在大于或等于500时才会 reject
},
data
})
}
重点:
axios的请求头默认为'application/json',
即axios会默认序列化 JavaScript 对象为 JSON.
如果想使用 application/x-www-form-urlencoded 格式,你可以使用下面的配置:
import Qs from 'qs'
export function getList(obj) {
const data = Qs.stringify(obj)
return fetch({
url: '',
method: 'POST',
headers: {
'content-type': 'application/x-www-form-urlencoded',
// 如果需要XMLHttpRequest,加入这个
'X-Requested-With': 'XMLHttpRequest'
},
data
})
}
然后在在vue文件中引入此函数来获取数据
// param为前端传入的参数
getList(param).then(res => {
if (res.data.code === 0) {
console.log(res.data.data);
this.allOrderTable = res.data.data.data;
this.pageTotal = res.data.data.total;
} else {
this.$message({
message: `[${res.data.msg}]:查询失败`,
type: "error"
});
}
this.listLoading = false;
})
.catch(() => {})
如果你想在稍后移除拦截器,可以这样:
var myInterceptor = axios.interceptors.request.use(function () {/*...*/});
axios.interceptors.request.eject(myInterceptor);
(4)使用 cancel token 取消请求:
(额,我好像没用到过(4))
可以使用 CancelToken.source
工厂方法创建 cancel token
var CancelToken = axios.CancelToken;
var source = CancelToken.source();
axios.get('/user/1111', {
cancelToken: source.token
}).catch(function(thrown) {
if (axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message);
} else {
// 处理错误
}
});
// 取消请求(message 参数是可选的)
source.cancel('Operation canceled by the user.');
还可以通过传递一个 executor 函数到 CancelToken
的构造函数来创建 cancel token:
var CancelToken = axios.CancelToken;
var cancel;
axios.get('/user/12345', {
cancelToken: new CancelToken(function executor(c) {
// executor 函数接收一个 cancel 函数作为参数
cancel = c;
})
});
// 取消请求
cancel();
注意,还可以使用同一个 cancel token 取消多个请求