Vue教程84--导航守卫

152 阅读3分钟

导航守卫

  • 我们来考虑一个需求: 在一个SPA应用中, 如何改变网页的标题呢?
    • 网页标题是通过<title>来显示的, 但是SPA只有一个固定的HTML, 切换不同的页面时, 标题并不会改变.
    • 但是我们可以通过JavaScript来修改<title>的内容.window.document.title = '新的标题'.
    • 那么在Vue项目中, 在哪里修改? 什么时候修改比较合适呢?
  • 普通的修改方式:
    • 我们比较容易想到的修改标题的位置是每一个路由对应的组件.vue文件中.
    • 通过mounted声明周期函数, 执行对应的代码进行修改即可.
    • 但是当页面比较多时, 这种方式不容易维护(因为需要在多个页面执行类似的代码).
  • 有没有更好的办法呢? 使用导航守卫即可.
  • 什么是导航守卫?
    • vue-router提供的导航守卫主要用来监听监听路由的进入和离开的.
    • vue-router提供了beforeEach和afterEach的钩子函数, 它们会在路由即将改变前和改变后触发

导航守卫使用

  • 我们可以利用beforeEach来完成标题的修改
  • 首先, 我们可以在钩子当中定义一些标题, 可以利用meta来定义
  • 其次, 利用导航守卫,修改我们的标题
  • 导航钩子的三个参数解析:
    • to: 即将要进入的目标的路由对象.
    • from: 当前导航即将要离开的路由对象.
    • next: 调用该方法后, 才能进入下一个钩子

main.js

 import Vue from 'vue'
 import App from './App'
 import router from './router'
 ​
 Vue.config.productionTip = false
 ​
 /* eslint-disable no-new */
 new Vue({
   el: '#app',
   router,
   render: h => h(App)
 })
 ​
 //前置钩子(hook)
 router.beforeEach(function (to,from,next){
   //从from到to的路由跳转
   document.title = to.meta.title
 })

index.js

 import Vue from 'vue'
 import Router from 'vue-router'
 import Home from "../components/Home";
 import About from "../components/About";
 import User from "../components/User";
 import News from "../components/homenews"
 import Message from "../components/homemessage"
 import Profile from "../components/profile"
 ​
 Vue.use(Router)
 ​
 const routes = [
   {
     path:"/",
     redirect:"/home"
   },
 ​
   // 非懒加载的路由
   {
     path:"/home",
     component:Home,
     meta:{
       title:"首页"
     },
     children:[
       {
         path:'',
         redirect:"news"
       },
       {
         path:"news",
         component:News
       },
       {
         path:"message",
         component:Message
       }
     ]
   }
   ,
   {
     path:"/about",
     component:About,
     meta:{
       title:"关于"
     }
   }
   ,
   {
     path:"/user/:userId",
     component:User,
     meta:{
       title:"用户"
     }
   },
   {
     path:"/profile/:id",
     component:Profile,
     meta:{
       title:"我的"
     }
   }
 ]
 ​
 ​
 const router = new Router({
   routes,
   mode:"history",
   linkActiveClass:"active"
 })
 ​
 export default router

我们在使用to.mate.title的时候会出现一个问题

  • 当我们切换首页的时候,要么无显示,要么显示undefined,其他三个显示的正常

  • 问题所在:

    • 我们使用的是嵌套路由,这样我们/home/news 而我们将meta属性放在了/home上,所以匹配不上,meta中没有数据,出现错误

  • 解决方法:

     router.beforeEach(function (to,from,next){
       //从from到to的路由跳转
       document.title = to.matched[0].meta.title
       console.log(to);
       next()
     })
    
  • 效果展示

导航守卫补充

  • 补充一:如果是后置钩子, 也就是afterEach, 不需要主动调用next()函数

     router.beforeEach(function (to,from,next){
       //从from到to的路由跳转
       document.title = to.matched[0].meta.title
       console.log(to);
       next()
     })
     ​
     router.afterEach((to,from)=>{
       console.log("------");
     })
    

  • 补充二: 上面我们使用的导航守卫, 被称之为全局守卫

    • 路由独享的守卫

      企业微信截图_20210908153824.png

    • 组件内的守卫

  • 更多内容, 可以查看官网进行学习: