当前位置: 移动技术网 > IT编程>开发语言>JavaScript > Vue中axios的封装(报错、鉴权、跳转、拦截、提示)

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

2019年09月06日  | 移动技术网IT编程  | 我要评论
  • 统一捕获接口报错
  • 弹窗提示
  • 报错重定向
  • 基础鉴权
  • 表单序列化

实现的功能

  • 统一捕获接口报错 : 用的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的封装(报错、鉴权、跳转、拦截、提示),希望对大家有所帮助

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网