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

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的信息?请移步 这里

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

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

您可能感兴趣的文章:

  • 详解VueRouter进阶之导航钩子和路由元信息
  • 详解使用Vue Router导航钩子与Vuex来实现后退状态保存
  • vue-router 导航钩子的具体使用方法
  • 详解vue-router 2.0 常用基础知识点之导航钩子
  • 非常实用的vue导航钩子
  • Vue+axios 实现http拦截及路由拦截实例
时间: 2018-04-07

详解vue-router 2.0 常用基础知识点之导航钩子

导航钩子 vue-router 提供的导航钩子主要用来拦截导航,让它完成跳转或取消.有多种方式可以在路由导航发生时执行钩子:全局的, 单个路由独享的, 或者组件级的. 全局钩子 const router = new VueRouter({ ... }) router.beforeEach((to, from, next) => { // do something next(); }); router.afterEach((to, from, next) => { console.log(to.

Vue+axios 实现http拦截及路由拦截实例

现如今,每个前端对于Vue都不会陌生,Vue框架是如今最流行的前端框架之一,其势头直追react.最近我用vue做了一个项目,下面便是我从中取得的一点收获. 基于现在用vue+webpack搭建项目的文档已经有很多了,我就不再累述了. 技术栈 vue2.0 vue-router axios 拦截器 首先我们要明白设置拦截器的目的是什么,当我们需要统一处理http请求和响应时我们通过设置拦截器处理方便很多. 这个项目我引入了element ui框架,所以我是结合element中loading和me

vue-router 导航钩子的具体使用方法

vue-router 提供的导航钩子主要用来拦截导航,让它完成跳转或取消. 全局钩子 1.router.beforeEach 注册一个全局的 before 钩子: const router = new VueRouter({ ... }) router.beforeEach((to, from, next) => { // ... }) 每个钩子方法接收三个参数: to: Route: 即将要进入的目标 路由对象 from: Route: 当前导航正要离开的路由 next: Function:

详解VueRouter进阶之导航钩子和路由元信息

导航钩子 vue-router 提供的导航钩子主要用来拦截导航,让它完成跳转或取消.有多种方式可以在路由导航发生时执行钩子:全局的, 单个路由独享的, 或者组件级的. 全局钩子 你可以使用 router.beforeEach 注册一个全局的 before 钩子: const router = new VueRouter({ ... }) router.beforeEach((to, from, next) => { // ... }) 当一个导航触发时,全局的 before 钩子按照创建顺序调用

非常实用的vue导航钩子

导航钩子 (译者:『导航』表示路由正在发生改变.) 正如其名,vue-router 提供的导航钩子主要用来拦截导航,让它完成跳转或取消.有多种方式可以在路由导航发生时执行钩子:全局的, 单个路由独享的, 或者组件级的. 全局钩子 你可以使用 router.beforeEach 注册一个全局的 before 钩子: const router = new VueRouter({ ... }) router.beforeEach((to, from, next) => { // ... }) 当一个导

详解使用Vue Router导航钩子与Vuex来实现后退状态保存

不好意思,标题比较啰嗦,因为这次的流水账确实属于一个比较细节的小东西,下面详细讲: 1需求 最近在使用electron-vue开发一个跨平台的桌面端软件,刚上手写了几个页面,遇到一个问题:桌面端软件通常会有导航需求,类似下图 导航按钮 点击返回按钮,返回上一页,并且显示上页内容.其实不止App,即使普通的网页中也会有此类需求,尤其是使用vue写SPA时. 项目中的导航几乎都是采用router.push({name: 'xxx', params: {xxx:123...}})这种方式.这种方式导致

android中Activity详解(生命周期、以各种方式启动Activity、状态保存,完全退出等)

一.什么是Activity? 简单的说:Activity就是布满整个窗口或者悬浮于其他窗口上的交互界面.在一个应用程序中通常由多个Activity构成,都会在Manifestxml中指定一个主的Activity,如下设置 <actionandroid:name="AndroidintentactionMAIN" /> 当程序第一次运行时用户就会看这个Activity,这个Activity可以通过启动其他的Activity进行相关操作.当启动其他的Activity时这个当前的

vue router导航守卫(router.beforeEach())的使用详解

导航守卫 导航守卫主要用来通过跳转或取消的方式守卫导航.有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的.(记住参数或查询的改变并不会触发进入/离开的导航守卫.你可以通过观察$route对象来应对这些变化,或使用beforeRouteUpdate的组件内守卫.) 好久没写一些东西了,总是感觉有啥缺少的.~~~~恰好碰到最近在写一个移动端项目,遇到了如何使同一个链接在不同条件下跳转到不同路由组件问题,譬如大家经常看到手机中没登录跳转登录页,登陆后跳转个人信息页等.废话不多说了

详解为什么Vue中不要用index作为key(diff算法)

前言 Vue 中的 key 是用来做什么的?为什么不推荐使用 index 作为 key?常常听说这样的问题,本篇文章带你从原理来一探究竟. 另外本文的结论对于性能的毁灭是针对列表子元素顺序会交换.或者子元素被删除的特殊情况,提前说明清楚,喷子绕道. 本篇已经收录在 Github 仓库,欢迎 Star: https://github.com/sl1673495/blogs/issues/39 示例 以这样一个列表为例: <ul> <li>1</li> <li>

详解在Vue.js编写更好的v-for循环的6种技巧

在VueJS中,v-for循环是每个项目都会使用的东西,它允许您在模板代码中编写for循环. 在最基本的用法中,它们的用法如下. <ul> <li v-for='product in products'> {{ product.name }} </li> </ul> 但是,在本文中,我将介绍六种方法来使你的 v-for 代码更加精确,可预测和强大. 让我们开始吧. 1.始终在v-for循环中使用key 首先,我们将讨论大多数Vue开发人员已经知道的常见最佳做

详解使用vue脚手架工具搭建vue-webpack项目

对于Vue.js来说,如果你想要快速开始,那么只需要在你的html中引入一个<script>标签,加上CDN的地址即可.但是,这并不算是一个完整的vue实际应用.在实际应用中,我们必须要一系列的工具,包括:模块化,转译,预处理,热加载,静态检测和自动化测试等.对于一个需要长期维护和大型的项目而言,这些工具是必不可少的,但是尝试配置初始化这些很痛苦.这就是我们发布vue官方提供的脚手架工具的原因,一个简单的构建工具,通过几个默认的步骤帮助你快速的构建Vue.js项目. 1.安装node环境 可以

详解利用 Vue.js 实现前后端分离的RBAC角色权限管理

项目背景:物业管理后台,不同角色拥有不同权限 采用技术:Vue.js + Vuex + Element UI 实现 RBAC 权限管理需要后端接口支持,这里仅提供前端解决方案. 因代码篇幅较大,对代码进行了删减,文中 "..." 即为省略的一部分代码. 大致思路: 首先登录成功后,从后台拉取用户当前可显示的菜单和可用权限列表,分别将其存入 store 的 nav(菜单导航) 和 auth(用户可用权限) 中,在用户切换路由时,判断是否存在 auth ,如果不存在,则重新获取,判断当前访

详解基于vue的移动web app页面缓存解决方案

现在移动web app越来越热门了,许多公司开始尝试使用angular.react.vue等MVVM框架来开发单页架构的web app.但在开发web app时,如果希望页面的导航体验也接近原生应用,那一般都会遇到这两个问题: 识别前进后退行为 后退时恢复之前的页面 笔者开发了一个基于vue与vue-router的导航库vue-navigation,来帮助开发者来解决这些问题,下面是问题的解决思路. 识别前进后退 先说第一个问题.和原生app不一样,浏览器中主要有这几个限制: 没有提供前进后退的