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

作者:Mr_Ma 时间:2024-05-02 17:06:03 

  • 统一捕获接口报错

  • 弹窗提示

  • 报错重定向

  • 基础鉴权

  • 表单序列化

实现的功能

  • 统一捕获接口报错 : 用的axios内置的 *

  • 弹窗提示: 引入 Element UI 的 Message 组件

  • 报错重定向: 路由钩子

  • 基础鉴权: 服务端过期时间戳和token,还有借助路由的钩子

  • 表单序列化: 我这边直接用 qs (npm模块),你有时间也可以自己写

用法及封装

用法


// 服务层 , import默认会找该目录下index.js的文件,这个可能有小伙伴不知道
// 可以去了解npm的引入和es6引入的理论概念
import axiosPlugin from "./server";
Vue.use(axiosPlugin);

对axios的封装(AXIOS: index.js )

import axios from "axios";
import qs from "qs";
import { Message } from "element-ui";
import router from "../router";
const Axios = axios.create({
baseURL: "/", // 因为我本地做了反向代理
timeout: 10000,
responseType: "json",
withCredentials: true, // 是否允许带cookie这些
headers: {
 "Content-Type": "application/x-www-form-urlencoded;charset=utf-8"
}
});
//POST传参序列化(添加请求 * )
Axios.interceptors.request.use(
config => {
 // 在发送请求之前做某件事
 if (
  config.method === "post"
 ) {
  // 序列化
  config.data = qs.stringify(config.data);
  // 温馨提示,若是贵公司的提交能直接接受json 格式,可以不用 qs 来序列化的
 }
 // 若是有做鉴权token , 就给头部带上token
 // 若是需要跨站点,存放到 cookie 会好一点,限制也没那么多,有些浏览环境限制了 localstorage 的使用
 // 这里localStorage一般是请求成功后我们自行写入到本地的,因为你放在vuex刷新就没了
 // 一些必要的数据写入本地,优先从本地读取
 if (localStorage.token) {
  config.headers.Authorization = localStorage.token;
 }
 return config;
},
error => {
 // error 的回调信息,看贵公司的定义
 Message({
  // 饿了么的消息弹窗组件,类似toast
  showClose: true,
  message: error && error.data.error.message,
  type: 'error'
 });
 return Promise.reject(error.data.error.message);
}
);
//返回状态判断(添加响应 * )
Axios.interceptors.response.use(
res => {
 //对响应数据做些事
 if (res.data && !res.data.success) {
  Message({
   // 饿了么的消息弹窗组件,类似toast
   showClose: true,
   message: res.data.error.message.message
    ? res.data.error.message.message
    : res.data.error.message,
   type: "error"
  });
  return Promise.reject(res.data.error.message);
 }
 return res;
},
error => {
 // 用户登录的时候会拿到一个基础信息,比如用户名,token,过期时间戳
 // 直接丢localStorage或者sessionStorage
 if (!window.localStorage.getItem("loginUserBaseInfo")) {
  // 若是接口访问的时候没有发现有鉴权的基础信息,直接返回登录页
  router.push({
   path: "/login"
  });
 } else {
  // 若是有基础信息的情况下,判断时间戳和当前的时间,若是当前的时间大于服务器过期的时间
  // 乖乖的返回去登录页重新登录
  let lifeTime =
   JSON.parse(window.localStorage.getItem("loginUserBaseInfo")).lifeTime *
   1000;
  let nowTime = new Date().getTime(); // 当前时间的时间戳
  console.log(nowTime, lifeTime);
  console.log(nowTime > lifeTime);
  if (nowTime > lifeTime) {
   Message({
    showClose: true,
    message: "登录状态信息过期,请重新登录",
    type: "error"
   });
   router.push({
    path: "/login"
   });
  } else {
   // 下面是接口回调的satus ,因为我做了一些错误页面,所以都会指向对应的报错页面
   if (error.response.status === 403) {
    router.push({
     path: "/error/403"
    });
   }
   if (error.response.status === 500) {
    router.push({
     path: "/error/500"
    });
   }
   if (error.response.status === 502) {
    router.push({
     path: "/error/502"
    });
   }
   if (error.response.status === 404) {
    router.push({
     path: "/error/404"
    });
   }
  }
 }
 // 返回 response 里的错误信息
 let errorInfo = error.data.error ? error.data.error.message : error.data;
 return Promise.reject(errorInfo);
}
);
// 对axios的实例重新封装成一个plugin ,方便 Vue.use(xxxx)
export default {
install: function(Vue, Option) {
 Object.defineProperty(Vue.prototype, "$http", { value: Axios });
}
};

路由钩子的调整(Router: index.js )


import Vue from "vue";
import Router from "vue-router";
import layout from "@/components/layout/layout";
// 版块有点多,版块独立路由管理,里面都是懒加载引入
import customerManage from "./customerManage"; // 客户管理
import account from "./account"; //登录
import adManage from "./adManage"; // 广告管理
import dataStat from "./dataStat"; // 数据统计
import logger from "./logger"; // 日志
import manager from "./manager"; // 管理者
import putonManage from "./putonManage"; // 投放管理
import error from "./error"; // 服务端错误
import { Message } from "element-ui";
Vue.use(Router);
// 请跳过这一段,看下面的
const router = new Router({
hashbang: false,
mode: "history",
routes: [
 {
  path: "/",
  redirect: "/adver",
  component: layout,
  children: [
   ...customerManage,
   ...adManage,
   ...dataStat,
   ...putonManage,
   ...manager,
   ...logger
  ]
 },
 ...account,
 ...error
]
});
// 路由拦截
// 差点忘了说明,不是所有版块都需要鉴权的
// 所以需要鉴权,我都会在路由meta添加添加一个字段requireLogin,设置为true的时候
// 这货就必须走鉴权,像登录页这些不要,是可以直接访问的!!!
router.beforeEach((to, from, next) => {
if (to.matched.some(res => res.meta.requireLogin)) {
 // 判断是否需要登录权限
 if (window.localStorage.getItem("loginUserBaseInfo")) {
  // 判断是否登录
  let lifeTime =
   JSON.parse(window.localStorage.getItem("loginUserBaseInfo")).lifeTime *
   1000;
  let nowTime = (new Date()).getTime(); // 当前时间的时间戳
  if (nowTime < lifeTime) {
   next();
  } else {
   Message({
    showClose: true,
    message: "登录状态信息过期,请重新登录",
    type: "error"
   });
   next({
    path: "/login"
   });
  }
 } else {
  // 没登录则跳转到登录界面
  next({
   path: "/login"
  });
 }
} else {
 next();
}
});
export default router;

axios可配置的一些选项,其他的具体看官网说明哈


export default {
// 请求地址
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",
// xsrf 设置
xsrfCookieName: "XSRF-TOKEN",
xsrfHeaderName: "X-XSRF-TOKEN",

// 下传和下载进度回调
onUploadProgress: function(progressEvent) {
 Math.round(progressEvent.loaded * 100 / progressEvent.total);
},
onDownloadProgress: function(progressEvent) {},

// 最多转发数,用于node.js
maxRedirects: 5,
// 最大响应数据大小
maxContentLength: 2000,
// 自定义错误状态码范围
validateStatus: function(status) {
 return status >= 200 && status < 300;
},
// 用于node.js
httpAgent: new http.Agent({ keepAlive: true }),
httpsAgent: new https.Agent({ keepAlive: true }),

// 用于设置跨域请求代理
proxy: {
 host: "127.0.0.1",
 port: 8080,
 auth: {
  username: "aa",
  password: "2123"
 }
},
// 用于取消请求
cancelToken: new CancelToken(function(cancel) {})
};

总结

这个封装虽说不是万金油版本,但是我感觉大多用axios结合vue的小伙伴,稍微改改都能直接拿来用

鉴权需要再严谨一些,比如token 可以遵循 JWT 的规格,以及引入中间层nodejs(对传输的做拦截封装加解密,聚合接口);

以上所述是小编给大家介绍的Vue中axios的封装(报错、鉴权、跳转、拦截、提示),希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

来源:https://juejin.im/post/5d5b5c1351882545bc5b9660

标签:Vue,axios,封装
0
投稿

猜你喜欢

  • 在Django model中设置多个字段联合唯一约束的实例

    2021-02-09 22:04:59
  • Oracle 数组的学习 小知识也要积累,养成好的学习态度

    2024-01-27 21:15:25
  • Pytorch 神经网络—自定义数据集上实现教程

    2022-11-30 20:05:04
  • 解决Django加载静态资源失败的问题

    2023-09-11 21:10:51
  • go格式“占位符”输入输出 类似python的input

    2021-04-23 21:32:18
  • SQL的Join使用图解教程

    2012-08-21 10:47:23
  • MySQL动态SQL拼接实例详解

    2024-01-20 15:13:55
  • laravel入门知识点整理

    2023-05-31 13:42:33
  • 未将对象引用设置到对象的实例 (System.NullReferenceException)

    2023-06-27 10:46:53
  • Django 实现图片上传和显示过程详解

    2022-06-13 22:22:27
  • Django 开发调试工具 Django-debug-toolbar使用详解

    2022-03-18 02:31:07
  • 详解使用python3.7配置开发钉钉群自定义机器人(2020年新版攻略)

    2022-05-10 01:18:53
  • MySQL 5.0默认100连接数的修改

    2008-11-05 13:34:00
  • vue递归获取父元素的元素实例

    2024-05-05 09:24:34
  • matplotlib基础绘图命令之imshow的使用

    2023-12-27 17:08:58
  • Django 限制访问频率的思路详解

    2021-08-17 16:52:57
  • CSS制作圆角导航的另一思路

    2008-11-06 11:39:00
  • JS实现监控微信小程序的原理

    2024-04-18 10:15:04
  • 老生常谈Python startswith()函数与endswith函数

    2023-06-03 02:02:42
  • Python制作词云的方法

    2021-08-26 19:52:20
  • asp之家 网络编程 m.aspxhome.com