背景
很多人在写前端代码的时候,都不做请求封装,这样容易出现的情况是,假设在一个项目中,有100个页面,每个页面都需要向服务器发送请求,来完成数据的交互,突然有一天,产品的哥们说,咱们得加个请求的验证,给请求交互的data里,加一个加密的数据,来保证数据的安全性,如果未进行封装的话,这100个页面中,每个请求都需要改一次,这就是个很庞大的工程,所以,我们在开始写代码的时候,对请求的封装,是一个很重要的设计
理解
所谓
操作
我们以Vue项目为例,使用vue-cli搭建项目,使axios来发送请求
文件结构如下
1 2 3 4 5 6 7 8 9 10 11 12
| my-projext |-node_modules |-public |-src |-assets |-components |-router |-store |-views |-App.vue |-main.js |-package.json
|
方法一:使用单独的文件来进行封装
首先,在src下新建一个文件夹api
并新建一个api.js
文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| my-projext |-node_modules |-public |-src + |-api + |-api.js |-assets |-components |-router |-store |-views |-App.vue |-main.js |-package.json
|
api.js
添加如下内容
1 2 3 4 5 6 7 8 9 10
| const apiUrl = 'https://www.yoursite.com/api/'; const axios = require('axios');
export function request(options = {}) { axios[options.methods]( apiUrl+options.url, options.data ).then(options.success) .catch(options.fail) }
|
经过这样的封装后,在页面中使用,就变成了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| page中
import {request} from '@/api/api.js'; export default { data(){ return {} }, methdos:{ getData(){ request({ url:"getData", data:{ param_1:'入参数据' }, success:(res)=>{ console.log('成功回调') } }) } } }
|
也可以在main.js
中进行统一引入,然后注入到Vue.prototype
中,这样就不用单独页面进行单独引入了
1 2 3 4 5 6 7 8 9
| //main.js import {request} from '@/api/api.js'; Vue.prototype.$request = request;
//Page中使用 this.$request({ url:'xxxxxx' })
|
这样的话,如果想在请求前增加请求拦截
,只需要在公共方法中,增加一个拦截即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| const apiUrl = 'https://www.yoursite.com/api/'; const axios = require('axios'); + const userData = require('@/api/userData.js');//引入放置用户信息的公共文件
export function request(options = {}) { + options=beforeRequest(options) axios[options.methods]( apiUrl+options.url, options.data - ).then(options.success) + ).then((res)=>{ + res=beforeResponse(res) + options.success&&options.success(res) + }) .catch(options.fail) }
+ export function beforeRequest(options = {}) {//请求前拦截的地方 + options.header = options.header||{} + options.header.token = userData.token; + return options + }
+ export function beforeResponse(res = {}) {//收到相应后拦截的地方 + if(res.header.status==200){ + if(res.data.resCode==0){ + //业务成功逻辑 + }else{ + //业务失败逻辑 + } + return res.data;//例如,只将回调中的data交给业务,而在拦截器里统一处理状态 + }else{ + alert("网络错误") + return res + } + }
|
方法二:Vuex中进行封装
我们将请求及请求拦截器,单独放置在vuex中的一个module
里
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| my-projext |-node_modules |-public |-src - |-api - |-api.js |-store + |- modules + |-api.js |- index.js |-assets |-components |-router |-views |-App.vue |-main.js |-package.json
|
api.js
中的代码为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| const axios = require('axios'); export default { state: { apiUrl:'https://www.yoursite.com/api/' }, mutations: {
}, actions: { request({state,commit,dispatch},options={}){//请求方法 this.dispatch('beforeRequest',options).then((options)=>{ axios[options.methods]( apiUrl+options.url, options.data ).then((res)=>{ return Promise.resolve(res) }).catch(options.fail) }).then((res)=>{ return this.dispatch('beforeRequest',options) }) }, beforeRequest({state,commit,dispatch},options={}){//请求前拦截 options.header = options.header||{} options.header.token = this.state.userData.token; return Promise.resolve(options) }, beforeResponse({state,commit,dispatch},res = {}) {//收到相应后拦截的地方 if(res.header.status==200){ if(res.data.resCode==0){ //业务成功逻辑 }else{ //业务失败逻辑 } return Promise.resolve(res.data);//例如,只将回调中的data交给业务,而在拦截器里统一处理状态 }else{ alert("网络错误") return Promise.reject(res) } } } }
|
Page
中的代码为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import {request} from '@/api/api.js'; export default { data(){ return {} }, methdos:{ getData(){ this.$store.dispatch('request',{ url:"getData", data:{ param_1:'入参数据' }, success: }).then((res)=>{ console.log('成功回调') }).catch(()=>{ console.log('失败回调') }) } } }
|