一、导航守卫

导航守卫:导航是正在发生变化的路由;从当前的组件离开准备去往下一个组件;

什么需要导航守卫?
真实项目中,我们需要根据用户权限、登录状态来决定用户可以看到的页面;但是路由就在浏览器地址栏里面,如果不加以拦截,用户通过在地址栏中输入,就可以看到他本不该看到的页面;所以我们使用导航守卫拦截它;

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <div id="app">
  9. <router-link to="/articles/1/x?name=mabin&age=18">文章1</router-link>
  10. <button @click="toArticle">去文章1</button>
  11. <router-view></router-view>
  12. </div>
  13. <template id="listTpl">
  14. <div>
  15. <div>LIST <button @click="goBack">返回</button></div>
  16. <div>
  17. <router-link to="/list/view">查看</router-link>
  18. <router-link to="/list/modify">修改</router-link>
  19. </div>
  20. <router-view></router-view>
  21. </div>
  22. </template>
  23. <script src="vue.js"></script>
  24. <script src="vue-router.js"></script>
  25. <script>
  26. let home = {
  27. template: `<div>HOME <button @click="toList">去列表</button></div>`,
  28. methods: {
  29. toList() {
  30. // 用方法切路由,push 是去指定的路由
  31. this.$router.push('/list')
  32. }
  33. }
  34. };
  35. let list = {
  36. template: `#listTpl`,
  37. methods: {
  38. goBack() {
  39. // 返回上一页(上一个组件)
  40. this.$router.go(-1);
  41. }
  42. }
  43. };
  44. let view = {
  45. template: `<div>查看</div>`
  46. };
  47. let modify = {
  48. template: `<div>修改</div>`
  49. };
  50. let articles = {
  51. template: `<div>第{{$route.params.id}}篇文章</div>`,
  52. created() {
  53. console.log(this.$route.params);
  54. console.log(this.$route.query);
  55. }
  56. };
  57. // /articles/1/x
  58. let routes = [
  59. {
  60. name: 'articles',
  61. path: '/articles/:id/:text',
  62. component: articles
  63. },
  64. {
  65. path: '/',
  66. component: home
  67. },
  68. {
  69. path: '/home',
  70. component: home
  71. },
  72. {
  73. path: '/list',
  74. component: list,
  75. children: [
  76. {
  77. path: 'view',
  78. component: view
  79. },
  80. {
  81. path: 'modify',
  82. component: modify
  83. }
  84. ]
  85. }
  86. ];
  87. let router = new VueRouter({
  88. routes
  89. });
  90. // 全局前置导航守卫: 对所有的路由都生效;
  91. router.beforeEach((to, from, next) => {
  92. // to 路由对象,包含将要去往的路由的信息
  93. // from 路由对象,包含了正要离开的路由的信息
  94. // next 控制权函数,如果通过验证执行 next() 交出控制权;
  95. console.log(to);
  96. console.log(from);
  97. // console.log(next);
  98. // 在这个函数中就可以做拦截,例如从 cookie 中获取登录状态,如果登录了,执行 next() 交出控制权;
  99. // next() 没有任何问题,交出控制权
  100. // next(false) 中断当前导航,如果 url 发生变化,会回退到当前页面的路由
  101. // next(路由或路由对象) 直接重定向到指定的路由
  102. // 无论哪种情况都要执行对应的 next,如果不执行就会处于挂起状态;
  103. let isLogin = document.cookie.includes('isLogin=true');
  104. // debugger;
  105. if (to.fullPath === '/list/view') {
  106. // /list/view 假设现在不需要验证权限,所以访问 /list/view 直接放行
  107. next()
  108. } else {
  109. if (isLogin) {
  110. next()
  111. } else {
  112. // next('/list/view'); // 重定向到 view
  113. next(false); // 中断导航,不能从当前页离开
  114. }
  115. }
  116. // next();
  117. });
  118. let vm = new Vue({
  119. el: '#app',
  120. router,
  121. methods: {
  122. toArticle() {
  123. // 点击 router-link 和执行下面的方法效果一样
  124. this.$router.push({
  125. name: 'articles',
  126. params: {id: 1, text: 'x'},
  127. query: {
  128. name: 'mabin',
  129. age: 18
  130. }
  131. })
  132. }
  133. }
  134. })
  135. </script>
  136. </body>
  137. </html>

二、路由独享守卫

  1. <body>
  2. <div id="app">
  3. <router-link to="/home">首页</router-link>
  4. <router-link to="/about">关于</router-link>
  5. <router-view></router-view>
  6. </div>
  7. <script src="vue.js"></script>
  8. <script src="vue-router.js"></script>
  9. <script>
  10. let home = {
  11. template: `<div>HOME</div>`
  12. };
  13. let about = {
  14. template: `<div>About</div>`
  15. };
  16. // 配置路由映射表
  17. let routes = [
  18. {
  19. path: '/',
  20. component: home
  21. },
  22. {
  23. path: '/home',
  24. component: home
  25. },
  26. {
  27. path: '/about',
  28. component: about,
  29. beforeEnter(to, from, next) {
  30. // 路由独享守卫:配置在路由映射表中
  31. console.log(to);
  32. console.log(from);
  33. console.log(next);
  34. // 在这个钩子中做校验,如果校验通过执行 next() 否则 next(false) 或者 重定向到某一个路由;
  35. next(); // 没问题放行
  36. // next(false); // 中断导航
  37. // next('/home'); // 重定向到某个路由
  38. // 无论执行哪一种 next,都要执行一个;
  39. }
  40. }
  41. ];
  42. // 创建 VueRouter 实例
  43. let router = new VueRouter({
  44. routes
  45. });
  46. let vm = new Vue({
  47. el: '#app',
  48. router
  49. })
  50. </script>
  51. </body>

三、组件内守卫

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <div id="app">
  9. <router-link to="/home">首页</router-link>
  10. <router-link to="/about/12">关于12</router-link>
  11. <router-link to="/about/13">关于13</router-link>
  12. <router-view></router-view>
  13. </div>
  14. <script src="vue.js"></script>
  15. <script src="vue-router.js"></script>
  16. <script>
  17. let home = {
  18. template: `<div>HOME</div>`
  19. };
  20. let about = {
  21. template: `<div>About</div>`,
  22. beforeRouteEnter(to, from, next) {
  23. // 在渲染路由对应的该组件前被调用,
  24. // 不!能!访问 this,因为此时 vue 实例尚未创建
  25. // to/from/next 和全局守卫一样的意义
  26. // next();
  27. // next(false);
  28. // next('/home')
  29. next();
  30. },
  31. beforeRouteUpdate(to, from, next) {
  32. // 当前路由发生改变,但是组件被复用(没销毁)时被调用;适用于动态路由的参数发生变化时
  33. // 要去往的路由参数 to.params
  34. // 正要离开的路由的参数 from.params
  35. console.log(to.params.id);
  36. console.log(from.params.id);
  37. next()
  38. },
  39. beforeRouteLeave(to, from, next) {
  40. // 导航要离开当前组件对应的路由时调用,从当前页去往其他页面的时候调用;可以用来做离开时提示用户信息没保存;
  41. let doLeave = confirm('信息尚未保存,确定要离开吗?');
  42. if (doLeave) {
  43. next()
  44. }
  45. }
  46. };
  47. // 配置路由映射表
  48. let routes = [
  49. {
  50. path: '/',
  51. component: home
  52. },
  53. {
  54. path: '/home',
  55. component: home
  56. },
  57. {
  58. path: '/about/:id',
  59. component: about,
  60. }
  61. ];
  62. // 创建 VueRouter 实例
  63. let router = new VueRouter({
  64. routes
  65. });
  66. let vm = new Vue({
  67. el: '#app',
  68. router
  69. })
  70. </script>
  71. </body>
  72. </html>

四、Vue-cli

cli初始化项目步骤.png