Code前端首页关于Code前端联系我们

1.啥是 vue-router?它在 Vue 项目里有啥用?

terry 3小时前 阅读数 8 #Vue
文章标签 router;路由

想搞懂 vue-router 咋在 Vue 项目里玩得转?不管是刚入门 Vue 的新手,还是想优化项目路由逻辑的开发者,这篇问答式教程能帮你把 vue-router 从基础到实战的知识点捋明白,下面从核心概念、配置方法到实际场景,一个个问题拆开来聊~

先理解「路由」本身——简单说就是“URL 路径和页面内容的对应关系”,比如访问 /home 显示首页组件,访问 /about 显示关于页组件。

Vue 做的是单页应用(SPA),整个项目就一个 HTML 文件,页面切换靠组件动态替换实现。vue-router Vue 官方的路由管理器,专门解决 SPA 里的三大问题:

  • 让不同 URL 对应不同组件,实现“多页感”的页面切换;
  • 管理 URL 里的参数、查询条件,让页面状态能通过 URL 保存和共享;
  • 支持嵌套路由、动态路由、权限控制这些复杂场景(比如后台系统的侧边栏+内容区结构)。

举个例子:做个人博客时,/article/123 对应文章详情组件,且能通过 URL 里的 123 加载对应文章——这就是 vue-router 帮你串联起来的。

咋在 Vue 项目里装 vue-router 并配置基础路由?

分「新建项目时集成」和「已有项目手动加」两种情况:

情况 1:用 Vue CLI 新建项目时选 router

执行 vue create my-project 后,CLI 会问你要不要装 vue-router,选「Y」就行,创建完后,项目里会自动生成 src/router/index.js(路由配置文件)和 src/views(放页面级组件)。

情况 2:给已有项目手动加 vue-router

  1. 先装依赖:终端执行 npm install vue-router@4(Vue3 用 v4,Vue2 用 v3,注意版本匹配);
  2. src 下新建 router 文件夹,创建 index.js,写基础配置:
    // src/router/index.js
    import { createRouter, createWebHistory } from 'vue-router'
    // 导入页面组件(也可以用懒加载,后面讲)
    import HomeView from '../views/HomeView.vue'
    import AboutView from '../views/AboutView.vue'
    

    const routes = [ { path: '/', // 访问根路径 name: 'home', component: HomeView }, { path: '/about', name: 'about', component: AboutView } ]

    const router = createRouter({ history: createWebHistory(), // HTML5 模式,URL 里没有 # routes // 上面定义的路由规则数组 })

    export default router

  3. main.js 里把 router 挂载到 Vue 根实例:
    // src/main.js
    import { createApp } from 'vue'
    import App from './App.vue'
    import router from './router' // 引入路由配置
    

    const app = createApp(App) app.use(router) // 注入路由 app.mount('#app')

配置完后,在 App.vue 里用 <router-view> 当“组件占位符”,用 <router-link> 做导航链接,

<template>
  <div>
    <router-link to="/">首页</router-link>
    <router-link to="/about">lt;/router-link>
    <router-view></router-view> 
  </div>
</template>
这样访问 时显示 HomeView,访问 /about 时显示 AboutView~

路由映射和组件渲染咋配合工作?

这里得分清两个核心对象:$router$route

  • $router 是路由实例(全局的,能调 push、replace 这些跳转方法);
  • $route 是当前路由对象(包含 path、params、query 这些当前 URL 的信息)。

<router-link><router-view> 是两个核心组件:

① <router-link> 负责生成导航链接

它默认渲染成 <a> 标签,to 属性指定目标路径,还能通过 tag 属性改成按钮、div 等,<router-link to="/" tag="button">首页</router-link> 就会渲染成按钮,点击照样跳转。

② <router-view> 负责渲染匹配的组件

它是个“占位容器”,Vue 会根据当前 URL 匹配 routes 里的规则,把对应的 component 渲染到 <router-view> 所在位置,比如访问 /about 时,AboutView 组件就会替换掉 <router-view>

举个实际流程:用户点 <router-link to="/about"> → URL 变成 /about → vue-router 匹配 routes 里 path 为 /about 的规则 → 把 AboutView 组件渲染到 <router-view> 里,整个过程不用刷新页面,这就是 SPA 的流畅体验~

路由传参有哪几种方式?各自咋用?

开发中经常需要把数据从一个页面传到另一个页面,vue-router 提供了 查询参数(query)动态路由参数(params)props 传参 三种常用方式,按需选:

方式 1:查询参数(query)—— 像 URL 里的 ?name=xxx

配置时不需要改 routes 里的 path,跳转时在 to 里加查询参数,比如从列表页跳详情页并传搜索关键词:

<!-- 模板里用 router-link -->
<router-link :to="{ name: 'articleDetail', query: { keyword: 'Vue' }}">详情</router-link>

<!-- 或者用 $router.push 编程式导航 --> this.$router.push({ name: 'articleDetail', query: { keyword: 'Vue' } })

目标组件里用 $route.query.keyword 接收参数,URL 会变成 /article-detail?keyword=Vue,刷新页面参数还在,适合传非敏感的筛选、搜索类信息。

方式 2:动态路由参数(params)—— 把参数嵌在 URL 路径里

适合传“必须的、标志性”的参数(比如文章 ID、用户 ID),需要先在 routes 里配置动态段(用 开头):

// routes 里加一条
{
  path: '/article/:id', // :id 是动态参数
  name: 'articleDetail',
  component: () => import('../views/ArticleDetail.vue') // 这里用了懒加载,后面讲
}

跳转时,把参数放到 params 里:

<router-link :to="{ name: 'articleDetail', params: { id: 123 }}">去文章 123</router-link>

<!-- 编程式导航 --> this.$router.push({ name: 'articleDetail', params: { id: 123 } })

目标组件里用 $route.params.id 拿参数,URL 是 /article/123,但要注意:如果用 path 跳转(而不是 name),params 会失效,所以更推荐用 name 配合 params

方式 3:props 传参—— 让组件更“纯”,解耦路由依赖

上面两种方式,组件里得用 $route.query$route.params 拿参数,这会让组件和路由强绑定,用 props 传参能解决这问题:

// routes 里配置时,开启 props: true
{
  path: '/article/:id',
  name: 'articleDetail',
  component: ArticleDetail,
  props: true // 把 $route.params 转成组件的 props
}

然后在 ArticleDetail 组件里定义 props 接收:

export default {
  props: ['id'], // 这样就能直接用 this.id 啦
  // ...
}

如果是 query 参数,想转 props 可以这么写:

props: (route) => ({
  keyword: route.query.keyword
})

这样组件里完全不用碰 $route,更符合组件化思想,日后维护或复用更方便~

导航守卫是干啥的?实际开发咋用?

导航守卫就是“路由跳转过程中的钩子函数”,能在路由跳转前、后做拦截或处理,常见场景:权限验证(比如没登录不让进个人中心)、页面跳转前保存表单数据、进入页面后加载数据。

vue-router 提供了全局守卫(整个应用的路由都生效)、路由独享守卫(只对某条路由生效)、组件内守卫(在组件里写的钩子),下面挑常用的讲:

① 全局前置守卫:router.beforeEach

router/index.js 里配置,每次路由跳转前都会触发,比如做登录验证:

// src/router/index.js
router.beforeEach((to, from, next) => {
  // to: 要跳转到的目标路由对象
  // from: 从哪个路由跳过来的
  // next: 必须调用,决定是否跳转(next() 放行,next('/login') 跳登录,next(false) 取消)

// 假设需要登录的页面,meta 里加 requiresAuth: true if (to.meta.requiresAuth && !isLogin()) { next('/login') // 没登录,跳登录页 } else { next() // 放行 } })

然后在 routes 里给需要权限的路由加 meta

{
  path: '/profile',
  name: 'profile',
  component: ProfileView,
  meta: { requiresAuth: true } // 标记需要登录
}

② 组件内守卫:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave

写在组件的选项里,比如进入文章详情页前加载数据(beforeRouteEnter):

export default {
  name: 'ArticleDetail',
  props: ['id'],
  data() { return { article: {} } },
  beforeRouteEnter(to, from, next) {
    // 注意:这里组件实例还没创建(this 是 undefined),所以请求数据可以放这里,或者用 next 的回调
    getArticle(to.params.id).then(res => {
      next(vm => { // vm 是组件实例
        vm.article = res.data
      })
    })
  },
  beforeRouteLeave(to, from, next) {
    // 离开页面时,比如判断表单是否修改,提示用户
    if (this.formEdited) {
      if (window.confirm('表单没保存,确定离开?')) {
        next()
      } else {
        next(false)
      }
    } else {
      next()
    }
  }
}

这些守卫能精细控制组件和路由的交互,处理权限、数据加载、页面离开提示这些场景特别顺手~

嵌套路由咋配置?适合啥场景?

嵌套路由就是“路由里套路由”,典型场景是后台管理系统:顶部导航+侧边栏+内容区,其中侧边栏切换时,内容区渲染不同子组件,但整体布局(顶部+侧边栏)不变。

配置分两步:父路由组件里放 <router-view> 给子路由用 + 在 routes 里用 children 数组定义子路由

举个后台系统的例子:

步骤 1:创建父组件(Layout)和子组件(Dashboard、Settings)

<!-- src/views/LayoutView.vue(父组件,负责整体布局) -->
<template>
  <div class="layout">
    <aside>侧边栏</aside>
    <main>
      <router-view></router-view> 
    </main>
  </div>
</template>
<!-- src/views/DashboardView.vue(子组件1) -->
<template><div>仪表盘内容</div></template>
<!-- src/views/SettingsView.vue(子组件2) -->
<template><div>设置页面内容</div></template>

步骤 2:在 routes 里配置嵌套路由

// src/router/index.js
const routes = [
  {
    path: '/admin',
    component: LayoutView, // 父组件
    children: [ // 子路由数组
      {
        path: 'dashboard', // 注意:路径不加 /,会自动拼接成 /admin/dashboard
        name: 'dashboard',
        component: DashboardView
      },
      {
        path: 'settings',
        name: 'settings',
        component: SettingsView
      },
      {
        path: '', // 子路由默认页面,访问 /admin 时显示
        redirect: 'dashboard' // 重定向到 dashboard
      }
    ]
  }
]

这样,访问 /admin/dashboard 时,LayoutView 会渲染,同时它内部的 <router-view> 会渲染 DashboardView;访问 /admin/settings 时,渲染 SettingsView,父组件的布局(侧边栏)始终保留,只切换内容区——这就是嵌套路由的核心作用~

动态路由和路由懒加载有啥区别?咋用?

这俩是不同维度的功能,解决不同问题:

① 动态路由:处理“路径参数变化但组件复用”的场景

比如用户列表页点不同用户,进入 /user/1/user/2,路径参数变了,但用的是同一个 UserDetail 组件,这时组件会复用,生命周期钩子(如

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门