文章目录

Vue 路由:Vue Router 配置与导航守卫

发布于 2026-04-18 07:23:25 · 浏览 10 次 · 评论 0 条

Vue 路由:Vue Router 配置与导航守卫

在 Vue.js 单页应用开发中,页面跳转和权限控制是核心功能。Vue Router 作为官方管理器,负责将 URL 路径映射到组件,并控制导航流程。以下指南将详细介绍如何从零配置路由,并利用导航守卫实现精准的权限拦截。


一、 基础环境搭建与配置

开始之前,确保已创建 Vue 3 项目。以下步骤将引导你完成安装与核心配置。

  1. 执行安装命令。
    在项目根目录下打开终端,运行以下命令安装 Vue Router 4:

    npm install vue-router@4
  2. 创建路由配置文件。
    src 目录下新建一个名为 router 的文件夹,并在其中新建 index.js 文件。该文件将作为路由的入口。

  3. 定义路由映射表。
    打开 src/router/index.js输入以下代码引入 Vue Router 并定义路由规则。这里我们将路径与具体的组件关联起来。

    import { createRouter, createWebHistory } from 'vue-router'
    import Home from '../views/Home.vue'
    import About from '../views/About.vue'
    
    // 定义路由数组
    const routes = [
      {
        path: '/',
        name: 'Home',
        component: Home
      },
      {
        path: '/about',
        name: 'About',
        component: About
      }
    ]
    
    // 创建路由实例
    const router = createRouter({
      history: createWebHistory(import.meta.env.BASE_URL),
      routes
    })
    
    // 导出路由实例
    export default router
  4. 挂载路由插件。
    打开 src/main.js引入刚才创建的路由实例,并使用 app.use 方法将其注册到 Vue 应用中。

    import { createApp } from 'vue'
    import App from './App.vue'
    import router from './router'
    
    const app = createApp(App)
    
    app.use(router)
    app.mount('#app')
  5. 设置路由出口。
    打开 src/App.vue,在模板中添加 <router-view> 组件。这是路由匹配到的组件渲染的地方。

    <template>
      <nav>
        <!-- 导航链接将在后面配置 -->
      </nav>
      <router-view/>
    </template>

二、 路由导航与参数传递

配置完成后,需要通过用户交互触发页面跳转。Vue Router 提供了声明式和编程式两种导航方式。

1. 声明式导航

  1. 使用 <router-link> 组件。
    该组件会被渲染为 <a> 标签。在 App.vue 或任何组件中,编写如下代码实现跳转:

    <router-link to="/">首页</router-link>
    <router-link to="/about">关于</router-link>

2. 编程式导航

当需要在逻辑代码中进行跳转(如表单提交成功后)时,使用路由实例的方法。

  1. 调用 router.push 方法。
    <script setup>获取路由实例并执行跳转:

    import { useRouter } from 'vue-router'
    
    const router = useRouter()
    
    const goHome = () => {
      router.push('/')
    }

3. 路由传参

在实际业务中,跳转往往伴随着数据传递。主要有两种方式:ParamsQuery

传参方式 URL 显示形式 特点说明 获取方式
Query /user?id=123 参数拼接在 URL 后面,类似 ?key=value,刷新不丢失 $route.query.id` | | **Params** | `/user/123` | 参数作为路径的一部分,刷新页面可能会丢失(需配合动态路由) | `$route.params.id
  1. 配置动态路由(用于 Params 传参)。
    src/router/index.js修改路由配置,使用冒号 : 定义动态段:

    {
      path: '/user/:id',
      name: 'User',
      component: () => import('../views/User.vue') // 懒加载写法
    }
  2. 发送参数。
    在组件中编写跳转逻辑:

    // Query 传参
    router.push({ path: '/user', query: { id: '123' } })
    
    // Params 传参
    router.push({ name: 'User', params: { id: '123' } })
  3. 接收参数。
    在目标组件(如 User.vue)中,使用 useRoute 获取数据:

    import { useRoute } from 'vue-router'
    
    const route = useRoute()
    console.log(route.params.id)
    console.log(route.query.id)

三、 导航守卫与权限控制

导航守卫主要用于通过跳转或取消的方式守卫导航。常见的场景是:用户未登录时禁止访问后台页面。

1. 全局前置守卫

这是最常用的守卫,注册router/index.js 中,对所有路由跳转进行拦截。

  1. 添加 beforeEach 钩子。
    在创建路由实例后,导出实例前,写入以下代码:

    // 假设我们有一个简单的函数检查 Token
    const isAuthenticated = () => {
      return !!localStorage.getItem('token')
    }
    
    router.beforeEach((to, from, next) => {
      // to: 即将进入的目标
      // from: 当前导航正要离开的路由
      // next: 必须调用该方法来 resolve 这个钩子
    
      if (to.meta.requiresAuth && !isAuthenticated()) {
        // 如果需要登录但未登录,强制跳转到登录页
        next({ name: 'Login' })
      } else {
        // 否则正常放行
        next()
      }
    })
  2. 配置路由元信息。
    在需要权限的路由配置中,添加 meta 字段标记:

    {
      path: '/admin',
      name: 'Admin',
      component: () => import('../views/Admin.vue'),
      meta: { requiresAuth: true } // 自定义字段,表示需要登录
    }

2. 路由独享守卫

如果只需要对某一个特定路由进行拦截,可以直接在路由配置上定义 beforeEnter

  1. 插入守卫字段。
    routes 数组的具体路由对象中,添加 beforeEnter

    {
      path: '/settings',
      component: Settings,
      beforeEnter: (to, from, next) => {
        // 仅在进入 /settings 路由时触发
        if (confirm('确定要进入设置页吗?')) {
          next()
        } else {
          next(false) // 取消当前的导航
        }
      }
    }

3. 组件内守卫

直接在组件内部定义路由逻辑,通常用于获取组件数据。

  1. 添加钩子函数。
    .vue 文件的 <script setup> 中,使用 onBeforeRouteLeaveonBeforeRouteUpdate

    import { onBeforeRouteLeave } from 'vue-router'
    import { ref } from 'vue'
    
    const isSaved = ref(false)
    
    onBeforeRouteLeave((to, from, next) => {
      // 如果用户未保存修改,提示确认
      if (!isSaved.value) {
        const answer = window.confirm('您有未保存的更改,确定要离开吗?')
        if (answer) {
          next()
        } else {
          next(false)
        }
      } else {
        next()
      }
    })

四、 导航解析流程解析

理解 Vue Router 的内部执行顺序对于排查路由问题至关重要。以下流程描述了从触发导航到最终渲染的完整过程。

当用户点击链接或调用 router.push 时,系统会按以下顺序执行检查:

graph TD Start[触发导航] --> GlobalBefore[全局前置守卫 beforeEach] GlobalBefore -- "next被调用" --> RouteConfig[路由配置重定向 beforeEnter] GlobalBefore -- "next被调用" --> AsyncComp[异步组件加载] RouteConfig -- "next被调用" --> ComponentBeforeEnter[组件内 beforeRouteEnter] AsyncComp -- "加载成功" --> ComponentBeforeEnter ComponentBeforeEnter -- "next被调用" --> GlobalResolve[全局解析守卫 beforeResolve] GlobalResolve -- "next被调用" --> NavigationConfirmed[导航被确认] NavigationConfirmed --> GlobalAfterEach[全局后置钩子 afterEach] GlobalAfterEach --> DOMUpdate[DOM 更新] DOMUpdate --> ComponentMounted[调用 beforeRouteEnter 的 next 回调]
  1. 触发导航。
    导航被触发。

  2. 调用失活组件的 beforeRouteLeave
    如果当前页面有离开守卫,执行它。通常用于阻止未保存的修改丢失。

  3. 调用全局的 beforeEach
    检查全局前置守卫。如果所有守卫都调用了 next(),则继续。

  4. 调用重用的组件内 beforeRouteUpdate
    如果当前组件是复用的(例如从 /users/1 跳到 /users/2),执行更新守卫。

  5. 调用路由配置里的 beforeEnter
    执行路由独享守卫。

  6. 解析异步路由组件。
    如果路由配置是懒加载的,加载对应的组件文件。

  7. 调用被激活的组件内 beforeRouteEnter
    执行进入组件的守卫。注意此时组件实例还没被创建,无法访问 this

  8. 调用全局的 beforeResolve
    导航确认前的最后一步。

  9. 导航被确认
    路由状态更新,URL 改变。

  10. 调用全局的 afterEach
    执行后置钩子。此时导航已经结束,可以用于更改页面标题或分析页面访问。

  11. 触发 DOM 更新。
    Vue 渲染新的组件。

  12. 调用 beforeRouteEnter 守卫中传给 next 的回调函数。
    组件实例创建完成后,执行之前在 beforeRouteEnter 中传给 next 的回调函数,可以访问组件实例。


五、 路由懒加载与性能优化

为了减少首屏加载时间,应将不同路由对应的组件分割成不同的代码块,只有当路由被访问时才加载对应组件。

  1. 替换静态导入。
    src/router/index.js 中,将原本的静态 import 语句修改为动态导入函数:

    // 修改前
    // import Home from '../views/Home.vue'
    
    // 修改后
    const Home = () => import('../views/Home.vue')
    const About = () => import('../views/About.vue')
    const Admin = () => import('../views/Admin.vue')
    
    const routes = [
      {
        path: '/',
        name: 'Home',
        component: Home
      },
      // ...
    ]
  2. 打包观察。
    当项目 运行 npm run build 时,你会注意到生成的 dist 目录中,各个组件被分离成单独的 .js 文件。浏览器只会在用户访问特定页面时才下载对应的文件。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文