Vue 项目中实现登陆拦截

1、路由拦截

  1. 若是开发的是后台管理项目,但愿必须登陆才能访问其余页面的话,就用下面的这种方式进行拦截
import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/components/Home/home'
import Login from '@/components/Login/login'

Vue.use(Router)

const router =  new Router({
  mode: 'history',   // 去除路由中的 # 号
  routes: [
    {
      path: '/',
      name: 'login',
      component: Login
    },
    {
      path: '/home',
      name: 'home',
      component: Home
    }
  ]
})

// 导航守卫
// 参数1 : to 目标路由对象
// 参数2 : from 来源路由对象
// 参数3 : next() 下一步
router.beforeEach((to, from, next) => {
  // 1. 判断是否是登陆页面
  // 是登陆页面
  if(to.path === '/login') {
    next()
  } else {
    // 不是登陆页面
    // 2. 判断 是否登陆过
    let token = localStorage.getItem('token')
    token ? next() : next('/login')
  }
})

export default router
  1. 若是开发的不是后台管理项目,并但愿能够看到某些不用登陆就能够访问的页面,就用这种方式进行拦截
import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/components/Home/home'
import Cart from '@/components/Cart/cart'
import Login from '@/components/Login/login'

Vue.use(Router)

const router =  new Router({
  mode: 'history',   // 去除路由中的 # 号
  routes: [
  	 {
      path: '/',
      name: 'home',
      component: Home
    },
    {
      path: '/cart',
      name: 'cart',
      meta: {
      	requireAuth: true,  // 添加该字段,表示进入这个路由是须要登陆的
      },
      component: Cart
    },
    {
      path: '/login',
      name: 'login',
      component: Login
    }
  ]
})

// 导航守卫
// 参数1 : to 目标路由对象
// 参数2 : from 来源路由对象
// 参数3 : next() 下一步
router.beforeEach((to, from, next) => {
	if (to.meta.requireAuth) {     // 判断该路由是否须要登陆权限
	 	let token = localStorage.getItem('token')
	    if (token) {              // 经过localStorage.getItem()获取当前的 token 是否存在
	        next()
	    }
	    else {
	        next({
	            path: '/login',
	            query: {
	            	redirect: to.fullPath    // 将跳转的路由path做为参数,登陆成功后跳转到该路由
	            }  
	        })
	    }
	}
	else {
	    next()
	}
})

export default router

    当一个导航触发时,全局前置守卫按照建立顺序调用。守卫是异步解析执行,此时导航在全部守卫 resolve 完以前一直处于 等待中。javascript

每一个守卫方法接收三个参数:vue

  • to: Route    ——>   即将要进入的目标 路由对象
  • from: Route    ——>   当前导航正要离开的路由
  • next: Function    ——>   必定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。

    next (): 进行管道中的下一个钩子。若是所有钩子执行完了,则导航的状态就是 confirmed (确认的)。
    next (false): 中断当前的导航。若是浏览器的 URL 改变了 (多是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
    next (’/’) 或者 next ({ path: ‘/’ }): 跳转到一个不一样的地址。当前的导航被中断,而后进行一个新的导航。你能够向 next 传递任意位置对象,且容许设置诸如 replace: true、name: ‘home’ 之类的选项以及任何用在 router-link 的 to prop 或 router.push 中的选项。
    next (error): (2.4.0+) 若是传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。java

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

2、拦截器

  1. 在 src 目录下新建一个 http 目录,在该目录下新建 http.js 文件
    在这里插入图片描述
  2. 在 http.js 文件里写上以下代码
import axios from 'axios'
import router from './../router'

// http request 拦截器
axios.interceptors.request.use(
  function(config) {
    if (localStorage.getItem('token')) {
      config.headers.Authorization = localStorage.getItem('token')
    }
    return config
  },
  function(err) {
    return Promise.reject(err)
  }
)

// http response 拦截器
axios.interceptors.response.use(
  function(response) {
    return response
  },
  function(error) {
    if (error.response) {
      switch (error.response.status) {
        case 401:
          // 401 清除 token 信息并跳转到登陆页面
          localStorage.removeItem('token')   // 清除本地的token
          // 只有在当前路由不是登陆页面才跳转
          router.currentRoute.path !== '/login' &&
          router.replace({
            path: '/login',
            query: {
              redirect: router.currentRoute.path
            }
          })
      }
    }
    // console.log(JSON.stringify(error))
    // console : Error: Request failed with status code 402
    return Promise.reject(error.response.data)
  }
)

export default axios
  1. 在 main.js文件里引入 http.js 文件
import Vue from 'vue'
import App from './App'
import router from './router'
import axios from './http/http'

// 将axios挂载到prototype上,在组件中能够直接使用this.axios访问
Vue.prototype.axios = axios

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
})
  1. 在组件里使用
methods: {
	this.axios.get('', {}).then(function(res) {
		console.log(res)
	})
}