-
上一篇:《Vue - 9 - Vuex》- https://blog.csdn.net/LawssssCat/article/details/104678900
-
Github - axios:https://github.com/axios/axios
-
Github - 测试代码(包括前后端): https://github.com/LawssssCat/vue-springboot-cros_jsonp
# 为什么网络封装
如果直接使用第三方网络框架,当需要更换框架或者重构时,异常恶心
因此,需要进行一步封装
# 选择什么网络模块
## 选择一: 传统的Ajax是基于XMLHttpRequest(XHR)
为什么不用它呢?
非常好解释, 配置和调用方式等非常混乱.
<mark>编码起来看起来就非常蛋疼</mark>.
所以真实开发中很少直接使用, 而是使用jQuery-Ajax
## 选择二: 在前面的学习中, 我们经常会使用jQuery-Ajax
相对于传统的 Ajax
非常好用.
为什么不选择它呢?
- 首先, 我们先明确一点: 在Vue的整个开发中都是不需要使用
jQuery
了. - 那么, 就意味着为了方便我们进行一个网络请求, 特意引用一个jQuery, 你觉得合理吗?
jQuery的代码1w+行.
Vue的代码才1w+行.
<mark>完全没有必要为了用网络请求就引用这个重量级的框架</mark>.
## 选择三: 官方在Vue1.x的时候, 推出了Vue-resource .
Vue-resource
的体积相对于jQuery小很多.
另外Vue-resource是官方推出的.
为什么不选择它呢?
- <mark>在
Vue2.0
退出后, Vue作者就在GitHub的Issues中说明了去掉vue-resource, 并且以后也不会再更新</mark>.
那么意味着以后vue-reource不再支持新的版本时, 也不会再继续更新和维护.
对以后的项目开发和维护都存在很大的隐患.
## 选择四: axios
在说明不再继续更新和维护vue-resource的同时,
<mark>作者还推荐了一个框架: axios
为什么不用它呢?</mark>
axios有非常多的优点, 并且用起来也非常方便.
稍后, 我们对他详细学习.
# 同源策略 sop
跨域访问问题:
根据 同源策略(SOP same origin policy)
我们的项目部署在 domain1.com
服务器上时, 是不能直接访问 domain2.com
服务器上的资料的.
解决方案:
这个时候, 我们利用 <script>
标签的 src
帮助我们去服务器请求到数据, 将数据当做一个 javascript
的函数来执行, 并且执行的过程中传入我们需要的 json
.
# jsonp
首先,要了解 jsonp
(JSON with padding) - “填充式的JSON”
这篇文章讲
jsonp
透彻:《jsonp原理详解——终于搞清楚jsonp是啥了》
在前端开发中, 我们一种常见的网络请求方式就是 JSONP
使用 JSONP
最主要的原因往往是为了 <mark>解决跨域访问的问题</mark>.
## JSONP
的原理是什么呢?
<mark>JSONP的核心在于通过 <script>
标签的 src
来帮助我们请求数据.</mark>
<mark>所以, 封装 jsonp
的核心就在于我们监听 window
上的 jsonp
进行回调时的名称.</mark>
## JSONP如何封装呢?
我们一起自己来封装一个处理JSONP的代码吧.
# axios 静态
Github - https://github.com/axios/axios
功能特点:
- 在浏览器中发送
XMLHttpRequests
请求 - 在
node.js
中发送http
请求 - 支持
Promise API
- 拦截请求和响应
- 转换请求和响应数据
- 等等
个人理解:
axios == ajax i/o system
## 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]])
如何发送请求呢?
我们看一下下边的案例
## 发送get请求演示
安装
npm i axios --save
// axios 跨域
import axios from 'axios'
// /home/multidata
// /home/data?type=sell&page=3
axios({
url: 'http://localhost:8001/home/multidata',
method: 'get'
}).then(value => {
console.log('http://localhost:8001/home/multidata', value)
})
// String[] types = { "phone", "book", "computer", "clothing", "daily-supply", "adult", "CD", "virtual" };
axios.get('http://localhost:8001/order/data', {
// 专门针对get请求的参数拼接
params: {
type: 'book',
page: 2
}
}).then(value => {
console.log('http://localhost:8001/order/data', value)
})
## axios 并发请求:axios.all([axios()…])
axios
.all([
axios({
url: 'http://localhost:8001/home/multidata',
method: 'get'
}),
axios.get('http://localhost:8001/order/data', {
// 专门针对get请求的参数拼接
params: {
type: 'book',
page: 3
}
})
])
.then(value => {
console.log('value', value)
return Promise.resolve(value)
})
.then(
axios.spread((res1, res2) => {
console.log('res1', res1)
console.log('res2', res2)
})
)
## 全局配置
在上面的示例中, 我们的BaseURL是固定的
事实上, 在开发中可能很多参数都是固定的.
这个时候我们可以进行一些抽取, 也可以利用axiox的全局配置
axios.defaults.baseURL = '123.207.32.32:8000'
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
## 常见配置
# 分布式概念
生产环境,一般使用 nginx 反向***,形成 分布式 的后台服务。
减轻服务器压力,增加灵活性
# axios 实例
上面说,通过反向***访问分布式服务,我们不需要在多个域中跨域访问。
(但是,下面我们假定没有 反向***,我们需要在多个环境下获取服务)
这样的话,只有全局的静态的 axios 显然是不行的。
我们需要 axios 实例,为我们准备环境。
// 创建对应的 axios 的实例1
const instance1 = axios.create({
baseURL: 'http://222.111.33.33:8000' ,
timeout: 5000
})
// 使用实例1
instance1({
rul: '/home/multidata'
}).then(res => {
console.log()res;
})
// 使用实例2
instance1({
rul: '/home/multidata'
}).then(res => {
console.log()res;
})
////////////////////////////////////////////////////////////
// 创建对应的 axios 的实例1
const instance2 = axios.create({
baseURL: 'http://222.111.33.33:8001' ,
timeout: 1000
})
// 使用实例1
instance1({
rul: '/home/multidata'
}).then(res => {
console.log()res;
})
// 使用实例2
instance1({
rul: '/home/multidata'
}).then(res => {
console.log()res;
})
# 封装 request 模块
创建目录 @/network
专门存放网络模块
创建 @/network/request.js
写网络请求代码
import axios from 'axios'
// 封装 request 模块
export function request (config) {
// 1. 创建 axios 的实例
const instance = axios.create({
baseURL: 'http://localhost:8001',
timeout: 5000
})
// 发送真正的网络请求
return instance(config)
}
然后用自己封装好的组件调用
代码下载:https://github.com/LawssssCat/vue-springboot-cros_jsonp
# ***
axios
提供了***,用于我们在发送每次请求或者得到相应后,进行对应的处理。
如何使用***呢?
中文 api 文档 - http://www.axios-js.com/docs/#Interceptors
## 请求拦截
在前面的代码中添加 成功拦截
import axios from 'axios'
// 封装 request 模块
export function request (config) {
// 1. 创建 axios 的实例
const instance = axios.create({
baseURL: 'http://localhost:8001',
timeout: 5000
})
// axios 的***
instance.interceptors.request.use(
config=> {
console.log('interceptor success', config)
// return config
},
err => {
console.log('interceptor err', err)
}
)
// 发送真正的网络请求
return instance(config)
}
拦截成功请求!
<mark>但是有报错</mark>,
TypeError: Cannot read property 'cancelToken' of undefined
at throwIfCancellationRequested (dispatchRequest.js?c4bb:12)
at dispatchRequest (dispatchRequest.js?c4bb:24)
原因:我们拦截的 value 配置信息 config
我们需要把请求的配置向下传递,才能正确发送请求
## 使用情况
由上面请求可见,***是真正可以进行请求拦截的
-
校验:<mark>我们可以对 config 中一些不符合服务器的要求给进行拦截</mark>
-
增强:<mark>其次,我们可以通过***,在发送请求前做一些操作</mark>
如:
在请求前,给界面添加 进度条
然后在收到响应,进行处理前,去掉进度条
等 -
携带信息:
比如:给请求携带 token 信息
## 响应拦截
响应拦截 同理
import axios from 'axios'
// 封装 request 模块
export function request (config) {
// 1. 创建 axios 的实例
const instance = axios.create({
baseURL: 'http://localhost:8001',
timeout: 5000
})
// axios 的***
instance.interceptors.request.use(
config => { // config 是 请求的配置信息
console.log('request interceptor success', config)
return config
},
err => {
console.log('request interceptor err', err)
}
)
instance.interceptors.response.use(response => {
console.log('response interceptor success', response)
return response
}, err => {
console.log('response interceptor err', err)
})
// 发送真正的网络请求
return instance(config)
}