一、路由拦截
- 如果开发的是后台管理项目,希望必须登录才能访问其他页面的话,就用下面的这种方式进行拦截
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
- 如果开发的不是后台管理项目,并希望可以看到某些不用登录就可以访问的页面,就用这种方式进行拦截
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 完之前一直处于 等待中。
每个守卫方法接收三个参数:
- 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() 注册过的回调。
确保要调用 next 方法,否则钩子就不会被 resolved。
二、拦截器
- 在 src 目录下新建一个 http 目录,在该目录下新建 http.js 文件
- 在 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
- 在 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/>'
})
- 在组件里使用
methods: {
this.axios.get('', {}).then(function(res) {
console.log(res)
})
}