vue中Axios的封装与API接口的管理详解

如图,面对一团糟代码的你~~~真的想说,What F~U~C~K!!!

回归正题,我们所要的说的axios的封装和api接口的统一管理,其实主要目的就是在帮助我们简化代码和利于后期的更新维护。

一、axios的封装
在vue项目中,和后台交互获取数据这块,我们通常使用的是axios库,它是基于promise的http库,可运行在浏览器端和node.js中。他有很多优秀的特性,例如拦截请求和响应、取消请求、转换json、客户端防御XSRF等。所以我们的尤大大也是果断放弃了对其官方库vue-resource的维护,直接推荐我们使用axios库。如果还对axios不了解的,可以移步axios文档

安装

npm install axios; // 安装axios

引入

一般我会在项目的src目录中,新建一个request文件夹,然后在里面新建一个http.js和一个api.js文件。http.js文件用来封装我们的axios,api.js用来统一管理我们的接口。

// 在http.js中引入axios
import axios from 'axios'; // 引入axios
import QS from 'qs'; // 引入qs模块,用来序列化post类型的数据,后面会提到
// vant的toast提示框组件,大家可根据自己的ui组件更改。
import { Toast } from 'vant'; 

环境的切换

我们的项目环境可能有开发环境、测试环境和生产环境。我们通过node的环境变量来匹配我们的默认的接口url前缀。axios.defaults.baseURL可以设置axios的默认请求地址就不多说了。

// 环境的切换
if (process.env.NODE_ENV == 'development') {
 axios.defaults.baseURL = 'https://www.baidu.com';}
else if (process.env.NODE_ENV == 'debug') {
 axios.defaults.baseURL = 'https://www.ceshi.com';
}
else if (process.env.NODE_ENV == 'production') {
 axios.defaults.baseURL = 'https://www.production.com';
}

设置请求超时

通过axios.defaults.timeout设置默认的请求超时时间。例如超过了10s,就会告知用户当前请求超时,请刷新等。

axios.defaults.timeout = 10000;

post请求头的设置post请求的时候,我们需要加上一个请求头,所以可以在这里进行一个默认的设置,即设置post的请求头为application/x-www-form-urlencoded;charset=UTF-8

axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
  • 请求拦截

我们在发送请求前可以进行一个请求的拦截,为什么要拦截呢,我们拦截请求是用来做什么的呢?比如,有些请求是需要用户登录之后才能访问的,或者post请求的时候,我们需要序列化我们提交的数据。这时候,我们可以在请求被发送之前进行一个拦截,从而进行我们想要的操作。

请求拦截

// 先导入vuex,因为我们要使用到里面的状态对象
// vuex的路径根据自己的路径去写
import store from '@/store/index';

// 请求拦截器axios.interceptors.request.use(
 config => {
 // 每次发送请求之前判断vuex中是否存在token
 // 如果存在,则统一在http请求的header都加上token,这样后台根据token判断你的登录情况
 // 即使本地存在token,也有可能token是过期的,所以在响应拦截器中要对返回状态进行判断
 const token = store.state.token;
 token && (config.headers.Authorization = token);
 return config;
 },
 error => {
 return Promise.error(error);
})

这里说一下token,一般是在登录完成之后,将用户的token通过localStorage或者cookie存在本地,然后用户每次在进入页面的时候(即在main.js中),会首先从本地存储中读取token,如果token存在说明用户已经登陆过,则更新vuex中的token状态。然后,在每次请求接口的时候,都会在请求的header中携带token,后台人员就可以根据你携带的token来判断你的登录是否过期,如果没有携带,则说明没有登录过。这时候或许有些小伙伴会有疑问了,就是每个请求都携带token,那么要是一个页面不需要用户登录就可以访问的怎么办呢?其实,你前端的请求可以携带token,但是后台可以选择不接收啊!

响应的拦截

// 响应拦截器
axios.interceptors.response.use(
 response => {
 // 如果返回的状态码为200,说明接口请求成功,可以正常拿到数据
 // 否则的话抛出错误
 if (response.status === 200) {
  return Promise.resolve(response);
 } else {
  return Promise.reject(response);
 }
 },
 // 服务器状态码不是2开头的的情况
 // 这里可以跟你们的后台开发人员协商好统一的错误状态码
 // 然后根据返回的状态码进行一些操作,例如登录过期提示,错误提示等等
 // 下面列举几个常见的操作,其他需求可自行扩展
 error => {
 if (error.response.status) {
  switch (error.response.status) {
  // 401: 未登录
  // 未登录则跳转登录页面,并携带当前页面的路径
  // 在登录成功后返回当前页面,这一步需要在登录页操作。
  case 401:
   router.replace({
   path: '/login',
   query: {
    redirect: router.currentRoute.fullPath
   }
   });
   break;

  // 403 token过期
  // 登录过期对用户进行提示
  // 清除本地token和清空vuex中token对象
  // 跳转登录页面
  case 403:
   Toast({
   message: '登录过期,请重新登录',
   duration: 1000,
   forbidClick: true
   });
   // 清除token
   localStorage.removeItem('token');
   store.commit('loginSuccess', null);
   // 跳转登录页面,并将要浏览的页面fullPath传过去,登录成功后跳转需要访问的页面
   setTimeout(() => {
   router.replace({
    path: '/login',
    query: {
    redirect: router.currentRoute.fullPath
    }
   });
   }, 1000);
   break;

  // 404请求不存在
  case 404:
   Toast({
   message: '网络请求不存在',
   duration: 1500,
   forbidClick: true
   });
   break;
  // 其他错误,直接抛出错误提示
  default:
   Toast({
   message: error.response.data.message,
   duration: 1500,
   forbidClick: true
   });
  }
  return Promise.reject(error.response);
 }
 }
});

响应拦截器很好理解,就是服务器返回给我们的数据,我们在拿到之前可以对他进行一些处理。例如上面的思想:如果后台返回的状态码是200,则正常返回数据,否则的根据错误的状态码类型进行一些我们需要的错误,其实这里主要就是进行了错误的统一处理和没登录或登录过期后调整登录页的一个操作。

要注意的是,上面的Toast()方法,是我引入的vant库中的toast轻提示组件,你根据你的ui库,对应使用你的一个提示组件。

封装get方法和post方法

我们常用的ajax请求方法有get、post、put等方法,相信小伙伴都不会陌生。axios对应的也有很多类似的方法,不清楚的可以看下文档。但是为了简化我们的代码,我们还是要对其进行一个简单的封装。下面我们主要封装两个方法:get和post。

get方法:我们通过定义一个get函数,get函数有两个参数,第一个参数表示我们要请求的url地址,第二个参数是我们要携带的请求参数。get函数返回一个promise对象,当axios其请求成功时resolve服务器返回 值,请求失败时reject错误值。最后通过export抛出get函数。

/**
 * get方法,对应get请求
 * @param {String} url [请求的url地址]
 * @param {Object} params [请求时携带的参数]
 */
export function get(url, params){
 return new Promise((resolve, reject) =>{
 axios.get(url, {
  params: params
 }).then(res => {
  resolve(res.data);
 }).catch(err =>{
  reject(err.data)
 })
});}

post方法:原理同get基本一样,但是要注意的是,post方法必须要使用对提交从参数对象进行序列化的操作,所以这里我们通过node的qs模块来序列化我们的参数。这个很重要,如果没有序列化操作,后台是拿不到你提交的数据的。这就是文章开头我们import QS from 'qs';的原因。如果不明白序列化是什么意思的,就百度一下吧,答案一大堆。

/**
 * post方法,对应post请求
 * @param {String} url [请求的url地址]
 * @param {Object} params [请求时携带的参数]
 */
export function post(url, params) {
 return new Promise((resolve, reject) => {
  axios.post(url, QS.stringify(params))
 .then(res => {
  resolve(res.data);
 })
 .catch(err =>{
  reject(err.data)
 })
 });
}

这里有个小细节说下,axios.get()方法和axios.post()在提交数据时参数的书写方式还是有区别的。区别就是,get的第二个参数是一个{},然后这个对象的params属性值是一个参数对象的。而post的第二个参数就是一个参数对象。两者略微的区别要留意哦!

axios的封装基本就完成了,下面再简单说下api的统一管理。

整齐的api就像电路板一样,即使再复杂也能很清晰整个线路。上面说了,我们会新建一个api.js,然后在这个文件中存放我们所有的api接口。

首先我们在api.js中引入我们封装的get和post方法

/**
 * api接口统一管理
 */
import { get, post } from './http'

现在,例如我们有这样一个接口,是一个post请求:

http://www.baiodu.com/api/v1/users/my_address/address_edit_before

我们可以在api.js中这样封装:

export const apiAddress = p => post('api/v1/users/my_address/address_edit_before', p);

我们定义了一个apiAddress方法,这个方法有一个参数p,p是我们请求接口时携带的参数对象。而后调用了我们封装的post方法,post方法的第一个参数是我们的接口地址,第二个参数是apiAddress的p参数,即请求接口时携带的参数对象。最后通过export导出apiAddress。

然后在我们的页面中可以这样调用我们的api接口:

import { apiAddress } from '@/request/api';// 导入我们的api接口
export default {
 name: 'Address',
 created () {
  this.onLoad();
 },
 methods: {
  // 获取数据
  onLoad() {
   // 调用api接口,并且提供了两个参数
   apiAddress({
    type: 0,
    sort: 1
   }).then(res => {
    // 获取数据成功后的其他操作
    ………………
   })
  }
 }
}

其他的api接口,就在pai.js中继续往下面扩展就可以了。友情提示,为每个接口写好注释哦!!!api接口管理的一个好处就是,我们把api统一集中起来,如果后期需要修改接口,我们就直接在api.js中找到对应的修改就好了,而不用去每一个页面查找我们的接口然后再修改会很麻烦。关键是,万一修改的量比较大,就规格gg了。还有就是如果直接在我们的业务代码修改接口,一不小心还容易动到我们的业务代码造成不必要的麻烦。

好了,最后把完成的axios封装代码奉上。

/**axios封装
 * 请求拦截、相应拦截、错误统一处理
 */
import axios from 'axios';import QS from 'qs';
import { Toast } from 'vant';
import store from '../store/index'

// 环境的切换
if (process.env.NODE_ENV == 'development') {
 axios.defaults.baseURL = '/api';
} else if (process.env.NODE_ENV == 'debug') {
 axios.defaults.baseURL = '';
} else if (process.env.NODE_ENV == 'production') {
 axios.defaults.baseURL = 'http://api.123dailu.com/';
}

// 请求超时时间
axios.defaults.timeout = 10000;

// post请求头
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';

// 请求拦截器
axios.interceptors.request.use(
 config => {
  // 每次发送请求之前判断是否存在token,如果存在,则统一在http请求的header都加上token,不用每次请求都手动添加了
  // 即使本地存在token,也有可能token是过期的,所以在响应拦截器中要对返回状态进行判断
  const token = store.state.token;
  token && (config.headers.Authorization = token);
  return config;
 },
 error => {
  return Promise.error(error);
 })

// 响应拦截器
axios.interceptors.response.use(
 response => {
  if (response.status === 200) {
   return Promise.resolve(response);
  } else {
   return Promise.reject(response);
  }
 },
 // 服务器状态码不是200的情况
 error => {
  if (error.response.status) {
   switch (error.response.status) {
    // 401: 未登录
    // 未登录则跳转登录页面,并携带当前页面的路径
    // 在登录成功后返回当前页面,这一步需要在登录页操作。
    case 401:
     router.replace({
      path: '/login',
      query: { redirect: router.currentRoute.fullPath }
     });
     break;
    // 403 token过期
    // 登录过期对用户进行提示
    // 清除本地token和清空vuex中token对象
    // 跳转登录页面
    case 403:
     Toast({
      message: '登录过期,请重新登录',
      duration: 1000,
      forbidClick: true
     });
     // 清除token
     localStorage.removeItem('token');
     store.commit('loginSuccess', null);
     // 跳转登录页面,并将要浏览的页面fullPath传过去,登录成功后跳转需要访问的页面
     setTimeout(() => {
      router.replace({
       path: '/login',
       query: {
        redirect: router.currentRoute.fullPath
       }
      });
     }, 1000);
     break;
    // 404请求不存在
    case 404:
     Toast({
      message: '网络请求不存在',
      duration: 1500,
      forbidClick: true
     });
    break;
    // 其他错误,直接抛出错误提示
    default:
     Toast({
      message: error.response.data.message,
      duration: 1500,
      forbidClick: true
     });
   }
   return Promise.reject(error.response);
  }
 }
);
/**
 * get方法,对应get请求
 * @param {String} url [请求的url地址]
 * @param {Object} params [请求时携带的参数]
 */
export function get(url, params){
 return new Promise((resolve, reject) =>{
  axios.get(url, {
   params: params
  })
  .then(res => {
   resolve(res.data);
  })
  .catch(err => {
   reject(err.data)
  })
 });
}
/**
 * post方法,对应post请求
 * @param {String} url [请求的url地址]
 * @param {Object} params [请求时携带的参数]
 */
export function post(url, params) {
 return new Promise((resolve, reject) => {
  axios.post(url, QS.stringify(params))
  .then(res => {
   resolve(res.data);
  })
  .catch(err => {
   reject(err.data)
  })
 });
}

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • vue实现的请求服务器端API接口示例

    本文实例讲述了vue实现的请求服务器端API接口.分享给大家供大家参考,具体如下: import axios from 'axios' import router from '@/router' axios.defaults.timeout = 3000 axios.defaults.baseURL = '' axios.interceptors.request.use( config => { // const token = getCookie('名称') config.data = con

  • vue 更改连接后台的api示例

    vue 更改连接后台的api,是更改在config文件夹下的index.js文件中的proxyTable的值. 如下代码,其中 10.1.166.88:8888/springTimes 为后台暴露出来的appi. dev: { env: require('./dev.env'), port: 8886, autoOpenBrowser: true, assetsSubDirectory: 'static', assetsPublicPath: '/', proxyTable: { '/api':

  • 详解vue配置后台接口方式

    在vueAdmin项目中有两种方式配置后端接口的方式,在此做下记录 第一种(代理方式) 在工程目录下 > config > index.js - 修改为如下配置 proxyTable: { '/api': { target: 'http://127.0.0.1:8000', pathRewrite: { '^/api': '' } } }, 在工程目录下 > src > api > user.js - 接口写法 import axios from 'axios' export

  • vue中Axios的封装与API接口的管理详解

    如图,面对一团糟代码的你~~~真的想说,What F~U~C~K!!! 回归正题,我们所要的说的axios的封装和api接口的统一管理,其实主要目的就是在帮助我们简化代码和利于后期的更新维护. 一.axios的封装 在vue项目中,和后台交互获取数据这块,我们通常使用的是axios库,它是基于promise的http库,可运行在浏览器端和node.js中.他有很多优秀的特性,例如拦截请求和响应.取消请求.转换json.客户端防御XSRF等.所以我们的尤大大也是果断放弃了对其官方库vue-reso

  • React项目中axios的封装与API接口的管理详解

    目录 前言 安装 引入 环境的切换 请求拦截 响应拦截 api的统一管理 总结 前言 在react项目中,和后台交互获取数据这块,我们通常使用的是axios库,它是基于promise的http库,可运行在浏览器端和node.js中.他有很多优秀的特性,例如拦截请求和响应.取消请求.转换json.客户端防御XSRF等.如果还对axios不了解的,可以移步axios文档. 安装 //使用npm安装 npm install axios; //使用yarn安装 yarn add axios 引入 在项目

  • vue中Axios的封装和API接口的管理示例详解

    目录 一.axios的封装 安装 引入 环境的切换 设置请求超时 post请求头的设置 请求拦截 响应的拦截 封装get方法和post方法 axios的封装基本就完成了,下面再简单说下api的统一管理. 2018.8.14更新 我们所要的说的axios的封装和api接口的统一管理,其实主要目的就是在帮助我们简化代码和利于后期的更新维护. 一.axios的封装 在vue项目中,和后台交互获取数据这块,我们通常使用的是axios库,它是基于promise的http库,可运行在浏览器端和node.js

  • Vue中Axios的封装与接口管理详解

    目录 一. Axios 的封装 安装 Axios 引入 接口管理 统一暴露接口 在组件中使用 补充:封装get方法和post方法 总结 一. Axios 的封装 在 Vue 项目中,和后台进行数据交互是频繁且不可或缺的,刚开始没进行 Axios 封装的时候,每次请求后台数据都是写的完整的路径,特别长,尤其是基准地址,每次都要复制一遍加在前面,冗余特别大.封装完 Axios 后,调用接口就简短多了,如果后期出现基准地址的改变,只需要在配置中更改一次即可. 安装 Axios npm install

  • Vue中axios的封装(报错、鉴权、跳转、拦截、提示)

    统一捕获接口报错 弹窗提示 报错重定向 基础鉴权 表单序列化 实现的功能 统一捕获接口报错 : 用的axios内置的拦截器 弹窗提示: 引入 Element UI 的 Message 组件 报错重定向: 路由钩子 基础鉴权: 服务端过期时间戳和token,还有借助路由的钩子 表单序列化: 我这边直接用 qs (npm模块),你有时间也可以自己写 用法及封装 用法 // 服务层 , import默认会找该目录下index.js的文件,这个可能有小伙伴不知道 // 可以去了解npm的引入和es6引入

  • vue中axios的封装问题(简易版拦截,get,post)

    第一步还是先下载axios npm install axios --save 第二步/src/utils/目录下建立一个htttp.js import axios from 'axios'; axios.defaults.timeout = 5000; axios.defaults.baseURL =''; //http request 拦截器 axios.interceptors.request.use( config => { // const token = getCookie('名称')

  • 关于Vue中axios的封装实例详解

    前言 axios 是 Vue 官方推荐的一个 HTTP 库,用 axios 官方简介来介绍它,就是: Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中. 作为一个优秀的 HTTP 库,axios 打败了曾经由 Vue 官方团队维护的 vue-resource,获得了 Vue 作者尤小右的大力推荐,成为了 Vue 项目中 HTTP 库的最佳选择. 虽然,axios 是个优秀的 HTTP 库,但是,直接在项目中使用并不是那么方便,所以,我们需要对其进行一

  • vue 使用axios 数据请求第三方插件的使用教程详解

    axios 基于http客户端的promise,面向浏览器和nodejs 特色 •浏览器端发起XMLHttpRequests请求 •node端发起http请求 •支持Promise API •监听请求和返回 •转化请求和返回 •取消请求 •自动转化json数据 •客户端支持抵御 安装 使用npm: $ npm i axiso 为了解决post默认使用的是x-www-from-urlencoded 去请求数据,导致请求参数无法传递到后台,所以还需要安装一个插件QS $ npm install qs

  • Vue中Router路由两种模式hash与history详解

    hash 模式 (默认) 工作原理: 监听网页的hash值变化 -> onhashchange事件, 获取location.hash 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载. 会给用户好像跳转了网页一样的感觉, 但是实际上没有跳转 主要用在单页面应用(SPA) // 模拟原理 // 监听页面hash值变化 window.onhashchange = function(){ // 获取当前url的哈希值 const _hash = locat

  • 基于vue中对鼠标划过事件的处理方式详解

    鼠标事件进行监听 需求中,在一个table(组件)表中,对于其中一列(该列为图片列),当鼠标划过该列的某个单元格子(图片)时,需要展示出该单元格子对应的遮罩层 翻阅了一些博客,发现好多都提到了mouse事件,如mouseover.mouseout.mouseenter.mouseleave,在之后我自己也通过这种方法进行了尝试. <template> <el-table :data="tableData" stripe style="width: 100%&

随机推荐