Vue中axios的封装(报错、鉴权、跳转、拦截、提示)
程序员文章站
2022-04-28 20:42:38
统一捕获接口报错
弹窗提示
报错重定向
基础鉴权
表单序列化
实现的功能
统一捕获接口报错 : 用的axios内置的...
- 统一捕获接口报错
- 弹窗提示
- 报错重定向
- 基础鉴权
- 表单序列化
实现的功能
- 统一捕获接口报错 : 用的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的封装(报错、鉴权、跳转、拦截、提示),希望对大家有所帮助