1 概述
- 别名:路由钩子、路由守卫、路由拦截
- 作用:对路由的跳转进行拦截
- 守卫类型
- 全局导航守卫:对整个项目做控制
- 路由独享守卫:对单个路由配置做控制
- 路由内守卫:对组件对应的路由做控制
- 回调参数
- to:表示目标路由
- from:表示当前路由
- next 表示两者之间的连接
- next() 默认连通
- next(true) 允许跳转,和next()相同
- next (false) 取消跳转
- next('/xxx') / next({ name: 'home', params: {},query: {} }) 跳转到指定路由
- next( vm => { } ) // vm指的是目标组件(组件前置守卫无法获取this,用vm代替)
2 全局导航守卫
2.1 全局前置守卫
-
使用场景
- 后台管理系统、社区app 做登录拦截
-
使用方法
// 进行登录判断,若有token,允许跳转,否则一律跳到登录页 import router from '@/router' import { getCookie } from '@/utils/cookie' router.beforeEach(( to,from,next ) => { // 前置守卫必须写next // next的参数 // next( false )不允许跳转 // next() == next( true )运行跳转 // next('/login') 拦截并跳转至指定路由 // 有重定向,先完成重定向跳转 if ( to.path == '/home/hot' ) { next() } // 判断token const token = getCookie(' _token') if ( token || to.path == '/login') {// 二次触发时to.path == '/login'成立,直接跳转 next() return } else { // 若没有token,且不是去登录页,强制转到登录页 next('/login') // 路由跳转,触发导航守卫再次执行该文件 } })
2.2 全局后置守卫
-
没有拦截功能,常用于跳转后提示信息
router.afterEach((to) => { if ( to.path == '/recommend' ) { Notify({ type: 'success', message: '通知内容' }); } })
2.3 全局更新守卫
-
使用与前置守卫相同
-
区别:是否完整遍历路由表
- 更新守卫要遍历完整路由表没有配置错误才跳转页面
3 路由独享守卫
-
只在设置守卫的路由生效
/* * 路由表 */ // 引入cookie.js import { getCookie } from '@/utils/cookie' import Vue from 'vue' import { Toast } from 'vant' Vue.use( Toast ) // 路由懒加载 const ShopCar = () => import(/* webpackChunkName: "group-ljun" */ '@/views/shopcar/index.vue') const Error = () => import(/* webpackChunkName: "group-ljun" */ '@/views/error/index.vue') const routeTable = [ { path: '/shopcar', component: ShopCar, beforeEnter ( to,from,next ) { console.log('to',to) const token = getCookie('_token') if ( token ) { next() } else { Toast.fail('您还没有登录,无法查看购物车,请先去登录') next( false ) } }, meta: { include: 'ShopCar' } }, { path: '*',// 必须放在配置最下面 - 错误路由配置 component: Error, meta: { include: 'Error' } } ] export default routeTable
4 组件内守卫
4.1 组件前置守卫
-
拦截组件的进入
-
执行: 创建组件实例前执行,这个时候没有组件,没有this
-
功能
- 判断是否有token,然后是否能进入当前页面
<template> <div class="mine"> 个人中心 </div> </template> <script> import { getCookie } from '@/utils/cookie' export default { beforeRouteEnter (to,from,next) { // 组件内的前置钩子 const token = getCookie('_token') if ( token ) { next() return ; } next( false ) } } </script>- 数据预载:进入组件前,提前得到数据,并将这个数据赋值给组件
<script> import request from '@/utils/request.js'; export default { async beforeRouteEnter ( to,from,next ) { // 数据预载 console.log(to,from,next) const result = await request({ url: '/ajax/search', params: { kw: '万达', cityId: 1, stype: 2 } }) // console.log("beforeRouteEnter -> result", result.data.cinemas.list ) next( vm => { // vm就是当前组件 -> 解决的就是这个钩子得不到this // vm.cinemas = result.data.cinemas.list 这么写可行吗? 不行 // 对象的合并 Object.assign() -> Vue.set/this.$set( 属性,属性值 ) vm.$set( vm.cinemas, JSON.stringify(result.data.cinemas.list)) next() }) }, data () { return { cinemas: {} } } } </script>
4.2 组件后置守卫
-
拦截组件离开
-
执行: 离开组件前,这个时候有组件,有this
-
功能
- 已填写部分表单未提交就跳转时进行
beforeRouteLeave ( to,from,next ) { // 将要离开组件了 if ( this.username || this.password ) { if (confirm('您还没有提交,确定要离开吗?')) { next() return; } else { next( false ) return; } } next() }
基础决定未来,一步一个脚印