1. 主页
  2. Vue2 教程
  3. Vue教程之导航守卫

Vue教程之导航守卫

导航守卫就是路由跳转过程中的一些钩子函数,再直白点路由跳转是一个大的过程,这个大的过程分为跳转前中后等等细小的过程,在每一个过程中都有一函数,这个函数能让你操作一些其他的事儿的时机,这就是导航守卫。

导航解析过程

  1. 导航被触发。
  2. 在失活的组件里调用 beforeRouteLeave 守卫。
  3. 调用全局的 beforeEach 守卫。
  4. 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
  5. 在路由配置里调用 beforeEnter
  6. 解析异步路由组件。
  7. 在被激活的组件里调用 beforeRouteEnter
  8. 调用全局的 beforeResolve 守卫 (2.5+)。
  9. 导航被确认。
  10. 调用全局的 afterEach 钩子。
  11. 触发 DOM 更新。
  12. 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。

全局前置守卫

全局前置守卫用于在路由配置生效之前进行一些动作,可以使用 router.beforeEach 创建全局前置守卫。

实例演示

router.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import Login from '../views/Login.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home,
    meta: {
      auth: true
    }
  },
  {
    path: '/login',
    name: 'Login',
    component: Login
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

Home.vue

<template>
  <div class="home">
    <h1>Home</h1>
  </div>
</template>

<script>

export default {
  name: 'Home'
}
</script>

Login.vue

<template>
  <div>
    <h1>Login</h1>
  </div>
</template>

main.js

router.beforeEach((to, from, next) => {
  /*
    to: 要跳转的地址
    from: 来自那个页面的跳转
    next: 回调函数,执行此回调函数,表示继续后续操作
  */
  var isLogin = false
  console.log(to, from)
  if (to.meta.auth && !isLogin) {
    // next('/login')
    // next(false) // 哪都不要动了,就在这。
    next(new Error('你还么有登陆。'))
  } else {
    next()
  }
  next()
})

router.onError(err => {
  console.log(err.message)
})

全局守卫还有全局解析守卫(beforeResolve)及全局后置守卫(afterEach)。可根据全局前置守卫自己研究练习一下。文档地址:https://router.vuejs.org/zh/guide/advanced/navigation-guards.html

路由独享守卫

路由独享守卫与全局前置守卫的方法参数是一样的。只不过他们两个的作用域是不一样的。

实例演示

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import Login from '../views/Login.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home,
    meta: {
      auth: true
    },
    beforeEnter: (to, from, next) => {
      /*
        to: 要跳转的地址
        from: 来自那个页面的跳转
        next: 回调函数,执行此回调函数,表示继续后续操作
      */
      var isLogin = false
      console.log(to, from)
      if (to.meta.auth && !isLogin) {
        // next('/login')
        // next(false) // 哪都不要动了,就在这。
        next(new Error('你还么有登陆。'))
      } else {
        next()
      }
      next()
    }
  },
  {
    path: '/login',
    name: 'Login',
    component: Login
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

组件守卫

beforeRouteEnter

在渲染该组件的对应路由被确认前调用。

不!能!获取组件实例 this,也就是不能直接使用 this,因为当守卫执行前,组件实例还没被创建。

不过,你可以通过传一个回调给 next 来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数。

<template>
  <div class="home">
    <h1>Home</h1>
  </div>
</template>

<script>

export default {
  name: 'Home',
  data () {
    return {
      content: 'Hello Home.'
    }
  },
  beforeRouteEnter (to, from, next) {
    // 在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数。
    next(vm => {
      console.log(vm.content)
    })
  }
}
</script>

beforeRouteUpdate

在当前路由改变,但是该组件被复用时调用。

举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。

可以访问组件实例 this。

<template>
  <div class="home">
    <h1>Home</h1>
    <router-link :to="'/' + p">跳转Home</router-link>
    <br>
    <br>
    <br>
    <input type="text" v-model="p">
  </div>
</template>

<script>

export default {
  name: 'Home',
  props: ['id'],
  data () {
    return {
      p: 123
    }
  },
  beforeRouteUpdate (to, from, next) {
    console.log('上次路由参数:', this.id) // 需要注意使用 this 每次获取的都是 from 的参数信息
    console.log('当前路由参数:', to.params.id) // 获取当前路由的参数
    next()
  }
}
</script>

beforeRouteLeave

导航离开该组件的对应路由时调用。

可以访问组件实例 this。

<template>
  <div class="home">
    <h1>Home</h1>
    <router-link to="/login">离开</router-link>
  </div>
</template>

<script>

export default {
  name: 'Home',
  beforeRouteLeave (to, from, next) {
    const leave = window.confirm('是否要离开此页面。')
    if (leave) {
      next()
    } else {
      next(false)
    }
  }
}
</script>

我们要如何帮助您?

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注