网络模块封装
一、选择什么网络模块
选择一 :传统的 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-resource 的同时,作者还推荐了一个框架: axios
- 为什么用它?
- axios 有非常多的优点 ,并且用起来也非常的方便。
二、jsonp
-
在前端开发中,我们一种常见的网络请求方式就是 JSONP
-
使用
JSONP
最主要的原因是为了解决跨域访问的问题。 -
JSONP 的原理是什么呢?
- JSONP 的核心在于通过 script 标签的 src 来帮助我们请求数据。
- 原因是我们的项目部署在domain1.com 服务器上时,是不能直接访问 domain2.com 服务器上的资料的。
- 这个时候,我们利用 script 标签的src 来帮助我们去服务器 请求 到数据,将数据当做一个 JavaScript的函数䣂执行,并且执行的过程中传入我们需要的 json。
- 所有,封装 jsonp 的核心就在于我们 监听 window上的 jsonp 进行回调的名称。
-
JSONP 如何封装呢?
-
我们一起自己来封装一个出来 JSONP的代码吧。
let count = 1 export default function originPJSONP(option) { // 1. 从传入的 option 中提取 URL const url = option.url; // 2. 在body中添加 script 标签 const body = document.getElementsByTagName('body')[0]; const script = document.createElement('script'); // 3. 内部生成一个 不重复的 callback const callback = 'jsonp' + count++; // 4. 监听 window 上的 jsonp 的调用 return new Promise((resolve, roject) => { try { window[callback] = function (result) { body.removeChild(script); resolve(result) } const params = handleParam(option.data); body.appendChild(script) } catch (e) { body.removeChild(script) reject(e) } }) }
function handleParam(data) { let url = '' for (let key in data) { let value = data[key] !== undefined ? data[key] : '' url += `&${key} = ${encodeURIComponent(value)}` } return url }
-
三、为什么选择 axios
1、功能特点:
- 在浏览器中发送 XMLHttpRequests 请求
- 在 node.js 中发送 http 请求
- 支持 Promise API
- 拦截请求和 响应
- 转换 请求 和 响应数据
- 等等
2、补充 : axios 名称的由来、个人理解
axios : Ajax i/o system
3、axios 请求方式
-
支持多种请求方式
- 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 请求
import axios from 'axios' export default { name: 'app', created() { // 提问: 为什么没有跨域问题 // 1. 没有请求参数 axios.get("http://www.liulongbin.top:3005/api/getlunbo") .then(res => { console.log(res); }).catch(err => { console.log(err); }) // 2. 有请求参数 axios.get('http://123.207.32.32:8000/home/data', {params: { type: 'sell', page: 1}}) .then(res => { console.log(res); }).catch(err => { console.log(err); }) } }
-
-
发送并发请求
-
有时候,我们可以需要同时发送两个请求
-
使用
axios.all
, 可以放入多个请求的数组, -
axios.all([])
返回的结果是一个数组,使用 axios.spread 可将数组 [res1,res2] 展开为 res1, res2// 2. axios 发送并发请求 axios .all([ axios({ url: "http://www.liulongbin.top:3005/api/getlunbo" }), axios({ url: "http://123.207.32.32:8000/home/data", params: { type: "sell", page: 3 } }) ]) .then(res => { axios.spread((res1, res2) => { console.log(res1); console.log(res2); }); });
-
-
-
全局配置
-
在上面的实例中,我们的 BaseURL 是固定的
-
事实上,在并发中肯很多参数都是固定的
-
这个时候我们可以进行一些抽取,也可以利用axios的全局配置
axios.defaults.baseURL = 'http://www.liulongbin.top:3005/api' axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlenconded';
// 提取全局配置 axios.defaults.baseURL = "http://www.liulongbin.top:3005/api" axios .all([ axios({ url: "/getlunbo" }), axios({ // url: "http://123.207.32.32:8000/home/data", url: "/getnewslist", }) ]) .then(res => { axios.spread((res1, res2) => { console.log(res1); console.log(res2); }); });
-
-
4、常见的配置选项
-
请求地址
- url: '/user',
-
请求类型
- method: 'get',
-
请求根路径
- baseURL: 'http://www.mt.com/api'
-
请求前的数据处理
- transformRequest: [function(data) {}],
-
自定义的请求头
- headers: {'x-Requested-With':'XMLHttpRequest'},
-
URL查询对象
- params:{id: 12},
5、axios 的实例
-
为什么要创建 axios 的实例呢
-
当我们从 axios 模块中导入对象时,使用的实例是默认的实例
-
当给该实例设置一些默认配置时,这些配置就被固定下来了。
-
但是后续开发中,某些配置可能会不太一样
-
比如某些请求需要使用特定的 baseURL 或者 timeout 或者 content-Type 等
-
这个时候,我们就可以创建新的实例,并且传入属于该实例的配置信息
// 创建新的实例 const axiosInstance = axios.create({ baseURL: 'http://123.207.32.32:8000', timeout: 5000, headers: {} })
-
```json
// 发送网络请求
axiosInstance({
url: '/category',
method: 'get'
}).then(res => {
console.log(res)
}).catch(err) => {
console.log(err)
}
6、axios 封装 (使用 Promise 进行封装)
import originAxios from 'axios'
export default function axios(option) {
return new Promise((reslove, reject) => {
// 1. 创建 axios 的实例
const instance =originAxios.create({
baseURL: 'api',
timeout: 5000
})
// 2. 传入对象进行网络请求
instance(option).then(res => {
resolve(res)
}).catch(err => {
reject(err)
})
})
}
7、如何使用拦截器
-
axios 提供了拦截器,用于我们在发送每次请求或者得到响应后,进行对应的处理。
-
如何使用拦截
// 配置请求和响应拦截 instance.interceptors.request.use(config => { // 请求拦截成功 console.log('来到了 request 拦截 success中') return config }, err => { // 请求拦截失败 console.log('request 拦截 failure 中') }) instance.interceptors.response.use(response => { // 响应拦截成功 console.log('来到了 response 拦截 success 中') return response.data }, err => { // 响应拦截失败 console.log('来到了 response 拦截 failure 中') return err })