选择什么网络模块?
vue中发送网络请求有非常多的方式, 那么, 在开发中, 如何选择呢?
-
选择一: 传统的Ajax是基于XMLHttpRequest(XHR)
为什么不用它呢?
非常好解释, 配置和调用方式等非常混乱.
编码起来看起来就非常蛋疼.
所以真实开发中很少直接使用, 而是使用jQuery-Ajax -
选择二: 在前面的学习中, 我们经常会使用jQuery-Ajax
相对于传统的Ajax非常好用.
为什么不选择它呢?
首先, 我们先明确一点: 在Vue的整个开发中都是不需要使用jQuery了.
那么, 就意味着为了方便我们进行一个网络请求, 特意引用一个jQuery, 你觉得合理吗?
jQuery的代码1w+行.
Vue的代码才1w+行.
完全没有必要为了用网络请求就引用这个重量级的框架. -
选择三: 官方在Vue1.x的时候, 推出了Vue-resource.
Vue-resource的体积相对于jQuery小很多.
另外Vue-resource是官方推出的.
为什么不选择它呢?
在Vue2.0退出后, Vue作者就在GitHub的Issues中说明了去掉vue-resource, 并且以后也不会再更新.
那么意味着以后vue-reource不再支持新的版本时, 也不会再继续更新和维护.
对以后的项目开发和维护都存在很大的隐患. -
选择四: 在说明不再继续更新和维护vue-resource的同时, 作者还推荐了一个框架: axios为什么不用它呢?
axios有非常多的优点, 并且用起来也非常方便.
稍后, 我们对他详细学习.
jsonp
在前端开发中, 我们一种常见的网络请求方式就是JSONP
使用JSONP最主要的原因往往是为了解决跨域访问的问题.
JSONP的原理是什么呢?
- JSONP的核心在于通过
<script>
标签的src来帮助我们请求数据. - 原因是我们的项目部署在domain1.com服务器上时, 是不能直接访问domain2.com服务器上的资料的.
- 这个时候, 我们利用
<script>
标签的src帮助我们去服务器请求到数据, 将数据当做一个javascript的函数来执行, 并且执行的过程中传入我们需要的json.
所以, 封装jsonp的核心就在于我们监听window上的jsonp进行回调时的名称.
JSONP如何封装呢?
跳转理解,这里不详细说明
为什么选择axios?
功能特点:
- 在浏览器中发送 XMLHttpRequests 请求
- 在 node.js 中发送 http请求
- 支持 Promise API
- 拦截请求和响应
- 转换请求和响应数据
- 等等
axiox请求方式
支持多种请求方式:
- axios(config)
- axios.request(config)
- axios.get(url[, config])
- axios.delete(url[, config])
- axios.head(url[, config])
- axios.post(url[, data[, config]])
- axios.put(url[, data[, config]])
- axios.patch(url[, data[, config]])
安装:
npm install axios
基本使用:
全局配置
在上面的示例中, 我们的BaseURL是固定的
事实上, 在开发中可能很多参数都是固定的.
这个时候我们可以进行一些抽取, 也可以利用axiox的全局配置
常见的配置选项
请求地址
url: '/user',
请求类型
method: 'get',
请根路径
baseURL: 'http://www.mt.com/api',
请求前的数据处理
transformRequest:[function(data){}],
请求后的数据处理
transformResponse: [function(data){}],
自定义的请求头
headers:{'x-Requested-With':'XMLHttpRequest'},
URL查询对象
params:{ id: 12 },
查询对象序列化函数
paramsSerializer: function(params){ }
request body
data: { key: 'aa'},
超时设置s
timeout: 1000,
跨域是否带Token
withCredentials: false,
自定义请求处理
adapter: function(resolve, reject, config){},
身份验证信息
auth: { uname: '', pwd: '12'},
响应的数据格式 json / blob /document /arraybuffer / text / stream
responseType: 'json',
带参请求
get:
axios({
url: 'http://123.207.32.32:8000/home/data',
// 专门针对get请求的参数拼接
params: {
type: 'pop',
page: 1
}
}).then(res => {
console.log(res);
})
并发请求
有时候, 我们可能需求同时发送两个请求
使用axios.all, 可以放入多个请求的数组.
axios.all([]) 返回的结果是一个数组,使用 axios.spread 可将数组 [res1,res2] 展开为 res1, res2
axios.all([
axios({
url: 'http://152.136.xxx.xx:7878/api/m5/home/multidata',
method: 'get'
}),
axios({
url: 'http://152.136.xxx.xx:7878/api/m5/home/data',
method: 'get',
params: {
type: 'pop',
page: 3
}
})
]).then(axios.spread((res1, res2) => {
console.log(res1);
console.log(res2);
}))
axios的实例封装
创建实例
为什么要创建axios的实例呢?
当我们从axios模块中导入对象时, 使用的实例是默认的实例.
当给该实例设置一些默认配置时, 这些配置就被固定下来了.
但是后续开发中, 某些配置可能会不太一样.
比如某些请求需要使用特定的baseURL或者timeout或者content-Type等.
这个时候, 我们就可以创建新的实例, 并且传入属于该实例的配置信息.
// 创建axios 实例
const instance = axios.create({
baseURL: 'http://152.136.xxx.xx:7878/api/m5',
timeout: 5000
})
//
// const instance2 = axios.create({
// url: ''
// })
instance({
url: '/home/multidata'
}).then((result) => {
console.log(result);
})
instance({
url: '/home/data',
params: {
type: 'pop',
page: 1
}
}).then(result => {
console.log(result);
});
封装
为了减少对第三方的依赖
main.js
request1({
url: '/home/data',
params: {
type: 'pop',
page: 1
}
}).then(res => {
console.log(res);
}).catch(err => {
console.log(err);
})
request.js
import axios from "axios";
// 使用Promise对其封装
// 实例一
export function request1(config) {
// 返回一个Promise
return new Promise((resolve, reject) => {
// config
const instance = axios.create({
baseURL: 'http://152.136.xxx.xx:7875/api/m5',
timeout: 5000
})
// 发送请求
instance(config)
.then(result => resolve(result))
.catch(error => reject(error))
})
}
// 实例二
export function request2() {
}
axios 已经封装了Promise 所以可以这样写
// 实例二
// 其实axios已经封装了Promise
export function request2(config) {
const instance = axios.create({
baseURL: 'http://152.136.xxx.xx:7875/api/m5',
timeout: 5000
})
// 发送请求
return instance(config);
}
拦截器
axios提供了拦截器,用于我们在发送每次请求或者得到相应后,进行对应的处理。
如何使用拦截器呢?
export function request2(config) {
// 创建实例
const instance = axios.create({
baseURL: 'http://152.136.185.210:7878/api/m5',
timeout: 5000
})
// 拦截器
// 请求拦截
instance.interceptors.request.use(success => {
// 拦截的处理 发送请求之前都可以做什么?
// 1. 当发送网络请求时,可以添加Loading动画,
// 2. 判断用户是否登录
// 3. 对请求参数进行验证等
console.log(success);
// 放行
return success;
}, error => {
// 请求拦截中错误拦截较少,通常都是配置相关的拦截
// 可能的错误比如请求超时,可以将页面跳转到一个错误页面中。
console.log("请求发送失败!");
})
// 响应拦截
instance.interceptors.response.use(success => {
// 响应的成功拦截中,主要是对数据进行过滤。
// 响应成功
return success;
}, error => {
// 响应的失败拦截中,可以根据status判断报错的错误码,跳转到不同的错误提示页面。
// 响应失败
})
// 发送请求
return instance(config);
}