Vue.js 路由守卫详解

Vue.js 是一个用于构建用户界面的渐进式框架。在大型应用中,路由是管理页面间导航的关键部分。Vue Router 提供了一系列的路由守卫,帮助开发者在用户导航到新页面时执行特定逻辑。本文将详细介绍 Vue.js 中的全部路由守卫,包括如何使用、适用场景以及一些补充说明。


一、路由守卫分类

Vue Router 中的路由守卫主要分为以下几类:

  1. 全局守卫

    • beforeEach

    • beforeResolve

    • afterEach

  2. 路由独享守卫

    • beforeEnter

  3. 组件内守卫

    • beforeRouteEnter

    • beforeRouteUpdate

    • beforeRouteLeave


二、全局守卫

全局守卫是对整个应用生效的,无论是从哪个页面到哪个页面,都会触发这些守卫。

1. beforeEach

beforeEach 是一个全局前置守卫,在每次导航发生前执行。常用于检查用户是否有权限访问某个页面。

使用方法:

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

Vue.use(VueRouter);

const router = new VueRouter({
  routes: [
    { path: '/', component: Home },
    { path: '/about', component: () => import('./views/About.vue') },
  ],
});

router.beforeEach((to, from, next) => {
  // 例如检查用户是否登录
  if (to.meta.requiresAuth && !isUserLoggedIn()) {
    next('/login');
  } else {
    next();
  }
});

export default router;

使用场景:

  • 权限控制:确保用户在进入某些受限页面前已经登录。

  • 全局设置:如每次导航前设置加载动画。

2. beforeResolve

beforeResolve 是全局解析守卫,它在组件内守卫和异步路由组件被解析之后才被调用。通常用于在确认导航前执行最后的异步操作。

使用方法:

router.beforeResolve((to, from, next) => {
  // 例如获取动态数据
  fetchData(to).then(() => {
    next();
  }).catch(() => {
    next(false); // 取消导航
  });
});

使用场景:

  • 异步数据获取:在导航确认前确保数据已经准备好。

3. afterEach

afterEach 是全局后置守卫,在每次导航完成后执行。与 beforeEach 不同,它没有 next 参数,因为导航已经完成。

使用方法:

router.afterEach((to, from) => {
  // 例如停止加载动画
  stopLoading();
});

使用场景:

  • 日志记录:记录每次导航的路径信息。

  • 全局设置:如修改页面标题或停止全局加载动画。


三、路由独享守卫

路由独享守卫是针对单个路由生效的。

beforeEnter

beforeEnter 守卫只在进入特定路由时触发,不会在组件重用时触发。它适用于为某个特定路由添加独立的导航逻辑。

使用方法:

const router = new VueRouter({
  routes: [
    {
      path: '/about',
      component: () => import('./views/About.vue'),
      beforeEnter: (to, from, next) => {
        if (hasPermission(to)) {
          next();
        } else {
          next('/login');
        }
      },
    },
  ],
});

使用场景:

  • 单页权限控制:为某个页面单独设置访问权限。

  • 数据预处理:在进入页面前获取必要的数据。


四、组件内守卫

组件内守卫是在组件定义内部使用的,它们只对所属组件的实例生效。

1. beforeRouteEnter

beforeRouteEnter 只有在进入路由时触发。它不同于其他守卫的一个关键点是,它不能直接访问 this,因为组件实例还未被创建。不过,可以通过回调函数在导航确认后访问组件实例。

使用方法:

export default {
  beforeRouteEnter(to, from, next) {
    next((vm) => {
      // 组件实例已经创建
      vm.fetchData();
    });
  },
  methods: {
    fetchData() {
      // 获取数据逻辑
    },
  },
};

使用场景:

  • 数据预处理:在组件渲染前预处理数据,并在导航完成后初始化数据。

2. beforeRouteUpdate

beforeRouteUpdate 在当前路由改变,但是依然渲染同一个组件时触发。适用于当一个动态参数变化时,需要重新获取数据的场景。

使用方法:

export default {
  beforeRouteUpdate(to, from, next) {
    this.fetchData();
    next();
  },
  methods: {
    fetchData() {
      // 根据新参数获取数据
    },
  },
};

使用场景:

  • 动态数据更新:响应路由参数的变化,重新获取或更新数据。

3. beforeRouteLeave

beforeRouteLeave 在导航离开组件对应的路由时调用。常用于确认用户是否保存了当前表单内容。

使用方法:

export default {
  beforeRouteLeave(to, from, next) {
    if (this.hasUnsavedChanges) {
      const answer = window.confirm('You have unsaved changes. Do you really want to leave?');
      if (answer) {
        next();
      } else {
        next(false);
      }
    } else {
      next();
    }
  },
  data() {
    return {
      hasUnsavedChanges: false,
    };
  },
};

使用场景:

  • 表单验证:阻止用户在表单未保存时意外离开页面。

  • 清理工作:在离开页面前执行清理或重置工作。


五、补充说明

  • 导航流程:Vue Router 的导航流程遵循以下顺序:

    1. 触发 beforeEach 全局前置守卫。

    2. 在路由配置中触发 beforeEnter 守卫。

    3. 解析异步路由组件。

    4. 触发 beforeRouteEnter 组件内守卫。

    5. 触发 beforeResolve 全局解析守卫。

    6. 完成导航。

    7. 触发 afterEach 全局后置守卫。

  • next 函数的使用next 函数控制导航的流程,可以接受以下参数:

    • next():继续当前导航。

    • next(false):中断当前导航。

    • next('/')next({ path: '/' }):导航到一个不同的路径。

  • 异步操作:在守卫中执行异步操作时,需要确保异步操作完成后调用 next,否则导航将被卡住。


六、总结

Vue.js 的路由守卫为我们提供了强大的工具来管理应用中的导航逻辑。通过灵活使用全局守卫、路由独享守卫和组件内守卫,我们可以轻松实现权限控制、数据预处理和用户交互保护等功能。希望通过这篇文章,你能够更好地理解并应用这些守卫,构建更健壮的 Vue.js 应用。

你可能感兴趣的:(vue.js,前端,javascript)