[TOC] >[success] # 路由守卫 ~~~ 1.具体介绍可以看路由章节 ~~~ >[info] ## 全局守卫 ~~~ 1.全局守卫的三个时期'beforeEach'、'beforeResolve'、'afterEach',三个时期具 体执行时期参考'路由守卫章节' ~~~ >[danger] ##### 使用'beforeEach' 做一个拦截登录 ~~~ 1.首先'beforeEach'是所有路由中最早触发的,因此我们整个登录拦截 在'beforeEach' 周期做操作 2.小提示:一般判断用户是否登录,都是根据'session' 来进行操作决定,因此我们 可以把'session' 数据保存在一个全局变量中,通过在'beforeEach'判断'session' 是否存在 3.根据上面的提示我们可以勾画出一个逻辑,用来判断保存全局'session'的值来 决定跳转页面的顺序,但是 我们可以在进一步优化,比如已经登录的用户,在访问 登录页我们让他直接跳转到首页,不需要用户再次点击登录 4.根据上面的两个提示基本可以勾勒出一个在'beforeEach'的一个登录判断 5.下面代码还需要自己创建一个'login.vue'的视图组件,和需要在'router' 文件夹 下的'router.js' 中去注册组件和路由之间的关系 6.下面的to调用的方法可以参考官方文档'https://router.vuejs.org/zh/api/#%E8%B7%AF%E7%94%B1%E5%AF%B9%E8%B1%A1' 这里再次说明下 这里的'to'等同于'route'和'$route' 因此他们的方法是通用的 7.下面的next中使用等同于'router-link' 中的'to'的使用方式,下面的next中网页跳转使 用的都是命名路由的方式 8.下面案例中'HAS_LOGINED' 表示全局储存的session,这面案例中false表 示没有登录,true表示登录 ~~~ * 在router 文件夹下的index.js 中书写一下代码 ~~~ import Vue from 'vue' import Router from 'vue-router' import routes from './router' Vue.use(Router) const router = new Router({ routes, }) // 到时候这里可以做一个全局变量专门保存session const HAS_LOGINED = false router.beforeEach((to, from, next)=>{ if(to.name !== 'login'){ if(HAS_LOGINED) next() else next({name:'login'}) }else{ if(HAS_LOGINED){ console.log('触发') next({name:'home'}) } else{ console.log('触发') next() } } }); export default router ~~~ >[danger] ##### 'beforeResolve' 详细可以参考路导航守卫章节 >[danger] ##### 'afterEach' 在路由结束时候去做一些事 ~~~ 1.注意'afterEach' 没有 'next' 因为已经是最后阶段了所以不需要'next()' ~~~ * 在 router 文件下的index.js 中配置这个周期(因为是最后一个周期所以不需要next 往下传递) ~~~ router.afterEach((to, from)=>{ console.log('都结束了') }); ~~~ >[info] ## 路由独享守卫 ~~~ 1.路由独享守卫'beforeEnter',在渲染改组件路由确认前调用 2.根据上面的解释,我们我可以推测出这方法应该写的位置,这个路由和组 件绑定的位置在我们这个目录中'router' 文件夹下的'router.js' 中去配置的, 路由和组件的关系,因此这个方法的调用也应该在这个地方 3.可以做一些 判断页面是从哪里来的判断 ~~~ >[danger] ##### 案例 * 在 router 文件下 的router.js 中进行路由独享守卫配置 ~~~ import Home from '@/views/Home.vue' export default [ { path: '/about', name: 'about', // 我是路由的一个属性是about 的专属 beforeEnter(to, from, next){ console.log('beforeEnter 路由中的路由'); next(); }, component: () => import(/* webpackChunkName: "about" */ '@/views/About.vue') }, ] ~~~ >[info] ## 组件内守卫 ~~~ 1.组件内守卫分三个阶段: 'beforeRouteEnter'、'beforeRouteUpdate'、'beforeRouteLeave'三个阶段会在不同时刻触发 2.'beforeRouteEnter' 在还没有进入该组件之前触发,一般用获取异步请求 ,可以替代vue生命周期中获取数据请求 3.'beforeRouteUpdate'在动态路由中使用,由于动态路由中切换路由的时候 ,犹豫绑定的是同一个组件因此在不会在重新渲染,但是为了可以让组件中 的内容重新渲染,有两种方法第一种使用watch 监听,但这种需要使 用'props'写法,另一种就是在'beforeRouteUpdate' 它会监听到动态路由的改 变,因此可以在这个周期中异步动态路由对应的数据 4.'beforeRouteLeave' 离开组件的时候触发,可以对表单一些校验未提交的 时候触发询问用户是否到下一个页面官方的说法这个离开守卫通常用来禁止 用户在还未保存修改前突然离开。该导航可以通过 next(false) 来取消。 ~~~ >[danger] ##### 案例 ~~~ 1.在'路由篇章中的导航守卫' 有详细的案例讲解,这里的案例只是简单说明 2.案例中做了一个离开询问 3..'beforeRouteUpdate'在动态路由中使用 这里具体用法见路由篇章 ~~~ ~~~ <template> <div class="about"> <h1>This is an about page</h1> </div> </template> <script> export default { beforeRouteEnter(to, from, next){ // 路由进入组件之前触发, // 正因为还没有进入组件前触发想获取组件实例本身也就是this,需要在next中操作 next( vm =>{ console.log(this) } ) }, beforeRouteLeave(to, from, next){ // 路由即将离开组件的时候调用 // 做一些询问,询问 const leave = confirm('你确定离开么') if(leave) next() else next(false) } } </script> ~~~ >[info] ## 路由元信息 ~~~ 1.路由元信息的便签属性是'meta',这个在html中是个常见的标签,有时候, 我们会把html 的meta一些配置参数放到这里,下面的案例就是动态生成, html的title 2.分析上面要做的事,首先每个页面都有'title',因此他们是公共的方法,可以给这 个方法提取到我们的'lib' 文件夹下的'util.js' 中 3.下面思考触发的时机,整个触发的时机最好的点就是'beforeEach'阶段是这个路 由最开始的阶段 4.我们在给'beforeEach'这个阶段使用我们定义的方法时候,两个知识点,一个是 要导入我们写的方法,另一个'if(条件){执行}'这种逻辑代码可以缩写成, '条件&&执行' ~~~ * 在lib的util.js 写的更改title方法(直接改变当前页面的title) ~~~ export const setTitle = (title)=>{ window.document.title = title || 'admin'; }; ~~~ * 在路由中定义 meta 的title 名称,这里我们只在about 的视图组件定义 ~~~ import Home from '@/views/Home.vue' export default [ { path: '/about', name: 'about', meta:{ title:"首页", }, beforeEnter(to, from, next){ next() }, component: () => import(/* webpackChunkName: "about" */ '@/views/About.vue') } ] ~~~ * 在router 文件下的index.js 配置的路由守卫'beforeEach'中配置 ~~~ import Vue from 'vue' import Router from 'vue-router' import routes from './router' import {setTitle} from "../lib/util"; Vue.use(Router); const HAS_LOGINED = true; const router = new Router({ routes }); router.beforeEach((to, from, next)=>{ to.meta && setTitle(to.meta.title); if(to.name ==='login'){ if(HAS_LOGINED) next({name:'home'}); else next() }else{ if(HAS_LOGINED) next(); else next({name:'login'}) } }); router.afterEach((to, from)=>{ console.log('都结束了') }); export default router ~~~