详解给Vue2路由导航钩子和axios拦截器做个封装


Posted in Javascript onApril 10, 2018

1.写在前面

最近在学习Vue2,遇到有些页面请求数据需要用户登录权限、服务器响应不符预期的问题,但是总不能每个页面都做单独处理吧,于是想到axios提供了拦截器这个好东西,再于是就出现了本文。

2.具体需求

  1. 用户鉴权与重定向:使用Vue提供的路由导航钩子
  2. 请求数据序列化:使用axios提供的请求拦截器
  3. 接口报错信息处理:使用axios提供的响应拦截器

3.简单实现

3.1 路由导航钩子层面鉴权与重定向的封装

路由导航钩子所有配置均在router/index.js,这里是部分代码

import Vue from 'vue'
import Router from 'vue-router'
import { getUserData } from '@/script/localUserData'

const MyAddress = r => require.ensure([], () => r(require('@/views/MyAddress/MyAddress')), 'MyAddress')

Vue.use(Router)

const routes = [
 {
  path: '/profile/address',
  name: 'MyAddress',
  component: MyAddress,
  meta: {
   title: '我的地址',
   requireAuth: true
  }
 },
 // 更多...
]

const router = new Router({
 mode: 'history',
 routes
})

我们主要来看下面逻辑处理部分的代码

let indexScrollTop = 0
router.beforeEach((to, from, next) => {
 // 路由进入下一个路由对象前,判断是否需要登陆
 // 在路由meta对象中由个requireAuth字段,只要此字段为true,必须做鉴权处理
 if (to.matched.some(res => res.meta.requireAuth)) {
  // userData为存储在本地的一些用户信息
  let userData = getUserData()
  // 未登录和已经登录的处理
  // getUserData方法处理后如果userData.token没有值就是undefined,下面直接判断
  if (userData.token === undefined) {
   // 执行到此处说明没有登录,君可按需处理之后再执行如下方法去登录页面
   // 我这里没有其他处理,直接去了登录页面
   next({
    path: '/login',
    query: {
     redirect: to.path
    }
   })
  } else {
   // 执行到说明本地存储有用户信息
   // 但是用户信息是否过期还是需要验证一下滴
   let overdueTime = userData.overdueTime
   let nowTime = +new Date
   // 登陆过期和未过期
   if (nowTime > overdueTime) {
    // 登录过期的处理,君可按需处理之后再执行如下方法去登录页面
    // 我这里没有其他处理,直接去了登录页面
    next({
     path: '/login',
     query: {
      redirect: to.path
     }
    })
   } else {
    next()
   }
  }
 } else {
  next()
 }
 if (to.path !== '/') {
  indexScrollTop = document.body.scrollTop
 }
 document.title = to.meta.title || document.title
})

router.afterEach(route => {
 if (route.path !== '/') {
  document.body.scrollTop = 0
 } else {
  Vue.nextTick(() => {
   document.body.scrollTop = indexScrollTop
  })
 }
})
export default router

至此,路由钩子层面的鉴权处理完毕,不过细心的你可能注意到:导航去登录页面调用的next方法里面有个query对象,携带了目标路由的地址,这是因为在登录成功后我们需要重定向到目标页面。

3.2 对axios拦截器封装

axios所有配置均在件script/getData.js文件,这里是本文件公共代码部分

```

import qs from 'qs'

import { getUserData } from '@/script/localUserData '

import router from '@/router '

import axios from 'axios'

import { AJAX_URL } from '@/config/index '

axios.defaults.baseURL = AJAX_URL

> axios请求拦截器代码

 ```
/**
 * 请求拦截器,请求发送之前做些事情
 */
axios.interceptors.request.use(
 config => {
  // POST || PUT || DELETE请求时先格式化data数据
  // 这里需要引入第三方模块qs
  if (
   config.method.toLocaleUpperCase() === 'POST' ||
   config.method.toLocaleUpperCase() === 'PUT' ||
   config.method.toLocaleUpperCase() === 'DELETE'
  ) {
   config.data = qs.stringify(config.data)
  }
  // 配置Authorization参数携带用户token
  let userData = getUserData()
  if (userData.token) {
   config.headers.Authorization = userData.token
  }
  return config
 },
 error => {
  // 此处应为弹窗显示具体错误信息,因为是练手项目,劣者省略此处
  // 君可自行写 || 引入第三方UI框架
  console.error(error)
  return Promise.reject(error)
 }
)

axios响应拦截器代码

/**
 * 响应拦截器,请求返回异常统一处理
 */
axios.interceptors.response.use(
 response => {
  // 这段代码很多场景下没用
  if (response.data && response.data.success === false) {
   // 根据实际情况的一些处理逻辑...
   return Promise.reject(response)
  }
  return response
 },
 error => {
  // 此处报错可能因素比较多
  // 1.需要授权处用户还未登录,因为路由段有验证是否登陆,此处理论上不会出现
  // 2.需要授权处用户登登录过期
  // 3.请求错误 4xx
  // 5.服务器错误 5xx
  // 关于鉴权失败,与后端约定状态码为500
  switch (error.response.status) {
   case 403:
    // 一些处理...
    break
   case 404:
    // 一些处理...
    break
   case 500:
    let userData = getUserData()
    if (userData.token === undefined) {
     // 此处为未登录处理
     // 一些处理之后...再去登录页面...
     // router.push({
     //  path: '/login'
     // })
    } else {
     let overdueTime = userData.overdueTime
     let nowTime = +new Date
     if (overdueTime && nowTime > overdueTime) {
      // 此处登录过期的处理
      // 一些处理之后...再去登录页面...
      // router.push({
      //  path: '/login'
      // })
     } else {
      // 极端情况,登录未过期,但是不知道哪儿错了
      // 按需处理吧...我暴力回到了首页
      router.push({
       path: '/'
      })
     }
    }
    break
   case 501:
    // 一些处理...
    break
   default:
    // 状态码辣么多,按需配置...
    break
  }
  return Promise.reject(error)
 }
)

想了解更多关于axios的信息?请移步 这里 。

这个封装很简单,面对复杂的业务肯定还需要更多的考量,但是对于一般的小项目或边缘业务也差不多够用了。最后希望这篇文章能对有需要的同学提供一些帮助。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jQuery 表单验证扩展(三)
Oct 20 Javascript
jquery实现图片滚动效果的简单实例
Nov 23 Javascript
js控制href内容的连接内容的变化示例
Apr 30 Javascript
全面解析Bootstrap布局组件应用
Feb 22 Javascript
jQuery简单自定义图片轮播插件及用法示例
Nov 21 Javascript
JavaScript微信定位功能实现方法
Nov 29 Javascript
Bootstrap php制作动态分页标签
Dec 23 Javascript
js获取元素的偏移量offset简单方法(必看)
Jul 05 Javascript
Angular客户端请求Rest服务跨域问题的解决方法
Sep 19 Javascript
通过vue写一个瀑布流插件代码实例
Sep 07 Javascript
JavaScript 替换所有匹配内容及正则替换方法
Feb 12 Javascript
vue 使用v-for进行循环的实例代码详解
Feb 19 Javascript
详解webpack 打包文件体积过大解决方案(code splitting)
Apr 10 #Javascript
Angular CLI在Angular项目中如何使用scss详解
Apr 10 #Javascript
vue2.0+koa2+mongodb实现注册登录
Apr 10 #Javascript
bing Map 在vue项目中的使用详解
Apr 09 #Javascript
详解Vue打包优化之code spliting
Apr 09 #Javascript
node实现基于token的身份验证
Apr 09 #Javascript
vue-cli扩展多模块打包的示例代码
Apr 09 #Javascript
You might like
simplehtmldom Doc api帮助文档
2012/03/26 PHP
PHP数据库表操作的封装类及用法实例详解
2016/07/12 PHP
让AJAX不依赖后端接口实现方案
2012/12/03 Javascript
文本框(input)获取焦点(onfocus)时样式改变的示例代码
2014/01/10 Javascript
百度判断手机终端并自动跳转js代码及使用实例
2014/06/11 Javascript
JavaScript使用二分查找算法在数组中查找数据的方法
2015/04/07 Javascript
Document.body.scrollTop的值总为零的快速解决办法
2016/06/09 Javascript
jQuery通过ajax快速批量提交表单数据
2016/10/25 Javascript
Node+Express+MongoDB实现登录注册功能实例
2017/04/23 Javascript
基于Vue和Element-Ui搭建项目的方法
2019/09/06 Javascript
vue 指令和过滤器的基本使用(品牌管理案例)
2019/11/04 Javascript
vue实现修改图片后实时更新
2019/11/14 Javascript
微信jssdk踩坑之签名错误invalid signature
2020/05/19 Javascript
[31:00]2014 DOTA2华西杯精英邀请赛5 24 NewBee VS iG
2014/05/25 DOTA
[01:21]辉夜杯战队访谈宣传片—CDEC
2015/12/25 DOTA
[48:26]VGJ.S vs infamous Supermajor 败者组 BO3 第二场 6.4
2018/06/05 DOTA
Python处理RSS、ATOM模块FEEDPARSER介绍
2015/02/18 Python
在Python中封装GObject模块进行图形化程序编程的教程
2015/04/14 Python
Python MySQLdb 使用utf-8 编码插入中文数据问题
2018/03/13 Python
opencv python 傅里叶变换的使用
2018/07/21 Python
对python中的argv和argc使用详解
2018/12/15 Python
Python 实现的 Google 批量翻译功能
2019/08/26 Python
Python基于内置库pytesseract实现图片验证码识别功能
2020/02/24 Python
Python进行特征提取的示例代码
2020/10/15 Python
Python使用struct处理二进制(pack和unpack用法)
2020/11/12 Python
python中altair可视化库实例用法
2021/01/26 Python
使用CSS3在触屏上为按钮实现激活效果
2013/09/27 HTML / CSS
美国购买汽车零件网站:Buy Auto Parts
2018/04/02 全球购物
澳大利亚当地最大的时装生产商:Cue
2018/08/06 全球购物
使用索引(Index)有哪些需要考虑的因素
2016/10/19 面试题
新年寄语大全
2014/04/12 职场文书
物业公司的岗位任命书
2014/06/06 职场文书
企业挂职心得体会
2014/09/10 职场文书
论文致谢词范文
2015/05/14 职场文书
2015年统战工作总结
2015/05/19 职场文书
SQL Server中交叉联接的用法详解
2021/04/22 SQL Server