GitHub项目地址:https://github.com/superman66/vue-axios-github/tree/master/src

router文件夹中的index.js添加路由权限校验

meta: { requireAuth: true, },

页面刷新时,重新赋值token

if (window.localStorage.getItem('token')) {
  store.commit(types.LOGIN, window.localStorage.getItem('token'))
}

在路由配置的最后,我们要利用vue-router提供的钩子函数beforeEach()对路由进行判断

router.beforeEach((to, from, next) => {
  if (to.matched.some(r => r.meta.requireAuth)) {
    if (store.state.token) {
      next();
    }
    else {
      next({
        name: 'login',
        param: {redirect: to.fullPath}
      })
    }
  }
  else {
    next();
  }
})

export default router;

每个钩子方法接收三个参数: 
* to: Route: 即将要进入的目标 路由对象 
* from: Route: 当前导航正要离开的路由 
* next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。 
* next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。 
* next(false): 中断当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。 
* next(‘/’) 或者 next({ path: ‘/’ }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。

确保要调用 next 方法,否则钩子就不会被 resolved。

在router文件夹中新建http.js,js中主要是统一处理http的请求和响应。通过配置http response inteceptor,当后端接口返回401 Unauthorized(未授权),让用户重新登录。

import axios from 'axios'
import store from './../store/store'
import * as types from './../store/types'
import router from './index'

// axios 配置
axios.defaults.timeout = 5000;

// http request 拦截器
axios.interceptors.request.use(
  config => {
    if (store.state.token) {
      config.headers.Authorization = `Bearer ${store.state.token}`;
    }
    return config;
  },
  err => {
    return Promise.reject(err);
  });

// http response 拦截器
axios.interceptors.response.use(
  response => {
    return response;
  },
  error => {
    if (error.response) {
      switch (error.response.status) {
        case 401:
          // 401 清除token信息并跳转到登录页面
          store.commit(types.LOGOUT);
          router.replace({
            name: 'HelloWorld',
            param: {redirect: router.currentRoute.fullPath}
          })
      }
    }
    // console.log(JSON.stringify(error));//console : Error: Request failed with status code 402
    return Promise.reject(error.response.data)
  });

export default axios;

通过上面这两步,就可以在前端实现登录拦截了。登出功能也就很简单,只需要把当前token清除,再跳转到首页即可。

由于项目中我们使用了vuex,所以我们需要新建一个store文件夹,它是vuex的状态管理文件夹。

每一个 Vuex 应用的核心就是 store(仓库)。"store" 基本上就是一个容器,它包含着你的应用中大部分的状态(state)。Vuex 和单纯的全局对象有以下两点不同:

  1. Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。

  2. 你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交(commit) mutations。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

创建 store 的过程很简单,只需要提供一些初始 state 对象和一些 mutations

store.js

import Vuex from 'vuex'
import Vue from 'vue'
import * as types from './types'

Vue.use(Vuex);
export default new Vuex.Store({
  state: {
    user: {},
    token: null,
    title: ''
  },
  mutations: {
    [types.LOGIN]: (state, data) => {
      localStorage.token = data;
      state.token = data;
    },
    [types.LOGOUT]: (state) => {
      localStorage.removeItem('token');
      state.token = null
    },
    [types.TITLE]: (state, data) => {
      state.title = data;
    }
  }
})

types.js

export const LOGIN = 'login';

export const LOGOUT = 'logout';

export const TITLE = 'title'

Vuex 主要有几个核心概念:

  • State: 状态,也就是数据来源,可以看作是组件中的 data,不过是抽离的公共数据。
  • Getters:可以理解为 store 的计算属性。
  • Mutations:更改 store 中的 state 的方法,类似于事件,每个 mutation 都有一个字符串的事件类型 (类似于事件的名称)和一个回调函数 (handler),这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数。 mutation 必须是同步函数。
  • Actions:Action 类似于 mutation,不过 Action 提交的是 mutation ,而不是直接变更状态,并且 Action 可以包含任何异步操作。
  • Modules:Vuex 允许我们将 store 分割成模块,避免当状态较多时, store 对象过于臃肿。

更多关于vuex请查看官方文档

在main.js中需要添加axios、store

new Vue({
  el: '#app',
  axios,
  router,
  store,
  components: { App },
  template: '<App/>'
})

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐