详解vue-router导航守卫

当做Vue-cli项目的时候需要在路由跳转前做一些验证,比如登录验证,是网站中的普遍需求。

对此,vue-router 提供的 beforeEach可以方便地实现全局导航守卫(navigation-guards)。组件内部的导航守卫函数使用相同,只是函数名称不同(beforeRouteEnter 、beforeRouteUpdate(2.2 新增) 、beforeRouteLeave)。

钩子(Hook),早期编程可能有个概念叫句柄,不知道将两者类比而且强行归为一类是不是合适。钩子的用处是在某个特定流程中的不同时机暴露出一些函数,使得用户可以通过覆写这些函数实现在原有位置执行自己的代码逻辑的功能。

1. 分类

vue-router中的导航钩子按定义位置不同(执行时机也不同)分为全局钩子、路由级钩子和组件级钩子。

  • 全局钩子

全局钩子有三个,分别是beforeEach、beforeResolve和afterEach,在路由实例对象注册使用;

  • 路由级钩子

路由级钩子有beforeEnter,在路由配置项中项定义;

  • 组件级钩子

组件级钩子有beforeRouteEnter、beforeRouteUpdate和beforeRouteLeave,在组件属性中定义;

官方文档地址:https://router.vuejs.org/zh-cn/advanced/navigation-guards.html

如何设置一个全局守卫

你可以使用 router.beforeEach 注册一个全局前置守卫:就是在你router配置的下方注册

const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
 // ...
})

当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 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。

一、认识beforeEach()中的参数

全局守卫(就是对整个路由实例进行守卫,对其中的子路由也会进行守卫)

路由独享的守卫(对实例中某个路由进行守卫)

小结:

全局和局部

import Vue from 'vue';
import VueRouter from 'vue-router';
// Vue中插件必须use注册
Vue.use(VueRouter);
// 路由配置项,此处是路由级钩子的定义
const routes = [{
    path: '/',
    component: resolve => require(['./index.vue'], resolve),
    keepAlive: true,
  },
  {
    path: '/user/:userName',
    keepAlive: true,
    beforeEnter(to,from,next){
      console.log('router beforeEnter');
      next();
    },
    component: resolve => require(['./user.vue'], resolve),
  }];
// 实例化路由对象
const router = new VueRouter({
  routes
});
// 全局钩子
router.beforeEach((to,from,next)=>{
  console.log('global beforeEach')
  next();
});
router.beforeResolve((to,from,next)=>{
  console.log('global beforeResolve')
  next();
});
router.afterEach((to,from,next)=>{
  console.log('global afterEach')
});
// 实例化Vue对象并挂载
new Vue({
  router
}).$mount('#app');

use.vue组件中使用导航守卫

<template>
  <div>
    <h1>{{ msg }}</h1>
    <p>我是:{{userName}}</p>
  </div>
</template>
<script>
  export default {
    name: 'user',
    data () {
      return {
        msg: '这里是 User Page.',
        userName: '叶落'
      };
    },
    methods: {},
    mounted () {
      var me = this;
      me.userName = me.$route.params.userName;
      console.log('user mounted.');
    },
    beforeRouteEnter (to, from, next) {
      console.log('component beforeRouteEnter');
      next();
    },
    beforeRouteUpdate (to, from, next) {
      console.log('component beforeRouteUpdate');
      next();
    },
    beforeRouteLeave(to,from,next){
      console.log('component beforeRouteLeave');
      next();
    }
  };
</script>

执行时机

由首页进入user页面:

global beforeEach > router beforeEnter > component beforeRouteEnter > global beforeResolve > global afterEach > mounted

由user回到首页:

component beforeRouteLeave => global beforeEach => global beforeResolve => global afterEach

排除beforeRouteUpdate,其余六个导航钩子的执行时机其实很好理解。大体按照leave、before、enter、resolve、after的顺序并全局优先的思路执行。beforeRouteUpdate的触发是在动态路由情形下,比如 path: '/user/:userName' 这条路由,当页面不变更只动态的改变参数userName时,beforeRouteUpdate便会触发。

结论:使用vue组件拼凑成整个应用,每个页面是独立的,路由依靠链接跳转,会刷新页面。使用vue-router则可以不刷新页面加载对应组件,hash和history模式模拟路径变化,不刷新页面。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持。如果你想了解更多相关内容请查看下面相关链接

(0)

相关推荐

  • vue中过滤器filter的讲解

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" con

  • 详解vue挂载到dom上会发生什么

    vue 挂载到dom 元素后发生了什么 前一篇文章分析了new vue() 初始化时所执行的操作,主要包括调用vue._init 执行一系列的初始化,包括生命周期,事件系统,beforeCreate和Created hook,在在这里发生,重点分析了 initState,即对我们常用到的data props computed 等等进行的初始化,最后,执行$mount 对dom进行了挂载,本篇文章将对挂载后所发生的事情进行进一步阐述, Vue.prototype.$mount = function

  • vue-router实现编程式导航的代码实例

    除了使用 <router-link> 创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写代码来实现.即:通过js动态的进行导航链接. 一.this.$router.push( ) router.push(location, onComplete?, onAbort?) 注意:在 Vue 实例内部,你可以通过 $router 访问路由实例.因此你可以调用 this.$router.push. 想要导航到不同的 URL,则使用 router.push 方法.这个方法会

  • Vue中Axios从远程/后台读取数据

    Axios从远程读取数据 学习Axios的知识,并把数据从远端读取到页面上.后端数据,只要调用相应的页面就可以调取,在实际开发中,这些后台数据是需要后端程序员和你共同讨论制作的.我们现在只做前端,数据大家只要会调用即可. 安装Axios 我们直接使用npm install来进行安装. cnpm install axios –save 由于axios是需要打包到生产环境中的,所以我们使用–save来进行安装. 引入Axios(在哪个模块中使用就在哪个模块中引入) 我们在.vue页面引入Axios,

  • vue计算属性computed、事件、监听器watch的使用讲解

    一.计算属性(computed) <template> <div class="box"> <h1>计算属性</h1> <hr> <!-- 直接渲染得到数据 --> <p><input type="text" v-model="message"></p> <!-- 对data的数据进行简单的操作 这样有一个不好的地方就是后期对页面数据

  • Vuex中的State使用介绍

    现在在上一篇为什么要使用Vuex的介绍理解基础上使用Vuex中的State,一个正面例子来证实,同时也介绍一下Vue核心概念State. Vuex 使用单一状态树--是的,用一个对象就包含了全部的应用层级状态.至此它便作为一个"唯一数据源 (SSOT)"而存在.这也意味着,每个应用将仅仅包含一个 store 实例.单一状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照. 单状态树和模块化并不冲突--在后面的章节里我们会讨论如何将状态和状态变

  • 在vue项目中引入highcharts图表的方法

    npm进行highchars的导入,导入完成后就可以进行highchars的可视化组件开发了 npm install highcharts --save 1.components目录下新建一个chart.vue组件 <template> <div class="chart" id="myChart" > <div class="emcs_charts" :id="id" ></div&

  • vue.js的vue-cli脚手架中使用百度地图API的实例

    第一步,去百度地图开发者申请密钥. 1.申请密钥(百度地图开放平台-->开发文档-->web开发-->JavaScript  API-->立即使用-->创建应用) 2.密钥申请成功后 第二步,在项目的需要模板中引入,具体如下: 项目路径 其中index.html存放地图链接,代码如下 在百度地图开放平台 服务介绍中 选择我们所需要的地图类型  demo演示可查看 选择我们所需哪种百度地图的类型:http://lbsyun.baidu.com/index.php?title=j

  • vue-router命名路由和编程式路由传参讲解

    有时候,通过一个名称来标识一个路由显得更方便一些,特别是在链接一个路由,或者是执行一些跳转的时候.你可以在创建 Router 实例的时候,在 routes 配置中给某个路由设置名称. 重点代码: 效果: 若有不足请多多指教!希望给您带来帮助! 总结 以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持.如果你想了解更多相关内容请查看下面相关链接

  • vue中轮训器的使用

    核心代码: <template> <div > {{log}} </div> </template> <script> export default { name: "TrainingInRotation", data(){ return { log:0, timerId:1, // 模拟计时器id,唯一性 timerObj :{}, // 计时器存储器 } }, created(){ this.startTraining()

随机推荐