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

vue-router 3.6 该怎么学?核心用法、实战场景全梳理

terry 3小时前 阅读数 11 #SEO

前端开发中,单页应用(SPA)的路由管理离不开 vue-router,作为 Vue2 生态的“老伙计”,vue-router 3.6 至今仍是很多项目的选择,但新手常困惑:它咋用?不同场景咋选方案?遇到 bug 咋解决?下面用问答形式,把核心知识点和实战技巧讲透。

vue-router 3.6 是什么?适合哪些前端项目?

vue-router 是 Vue.js 官方的路由管理器,专门解决单页应用的“路径与组件对应”“页面跳转不刷新”“权限控制”等问题。

6 版本属于 Vue2 生态专属(Vue3 要搭配 vue-router 4+),所以如果你在做这些项目,它就是刚需:

  • 企业后台系统(如 ERP、OA):需要复杂路由嵌套、权限拦截;
  • 营销官网 / 个人博客:需要多页面切换、动态路由(如文章详情页);
  • 移动端 H5 应用:需要 Hash 模式兼容低版本浏览器,或 History 模式做 SEO 优化。

简单说,只要是 Vue2 技术栈的 SPA,想让“URL 变化对应组件切换”,vue-router 3.6 就是标配。

从零开始,怎么搭建 vue-router 3.6 的基础路由?

想让路由跑起来,分 4 步:

① 安装依赖

命令行执行:

npm install vue-router@3.6.5 --save

(指定 3.6.5 版本,避免自动装到 4.x 踩坑)

② 配置路由实例(新建 router.js

import Vue from 'vue'
import VueRouter from 'vue-router'
// 导入页面组件(先学基础,暂时不用懒加载)
import Home from './views/Home.vue'
import About from './views/About.vue'
Vue.use(VueRouter) // 注册路由插件
// 定义路由规则:path 对应 URL,component 对应组件
const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About }
]
// 创建路由实例
const router = new VueRouter({
  routes, // 传入规则
  mode: 'history' // 路由模式:history(美观但需后端配置)或 hash(带#,兼容性好)
})
export default router

③ 注入到 Vue 根实例(修改 main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router.js' // 导入路由实例
new Vue({
  router, // 注入路由,让所有组件能通过 this.$router / this.$route 访问
  render: h => h(App)
}).$mount('#app')

④ 页面中使用路由组件

App.vue(或布局组件)里,用 <router-link> 做导航,<router-view> 做组件挂载点:

<template>
  <div id="app">
    <!-- 导航链接:to 属性指定路径 -->
    <router-link to="/">首页</router-link>
    <router-link to="/about">lt;/router-link>
    <!-- 路由组件的挂载点:匹配到的组件会渲染到这里 -->
    <router-view></router-view>
  </div>
</template>

现在访问 http://localhost:8080/ 会显示 Home 组件,访问 /about 显示 About 组件,基础路由就跑通了!

动态路由匹配有啥用?怎么处理参数变化?

动态路由URL 里带“可变参数”,比如用户详情页 /user/1/user/2 共用一个组件。

① 配置动态路由规则

router.js 里定义带参数的路径(用 参数名 标记):

{ path: '/user/:id', component: User }

② 组件内获取参数

User 组件里,通过 this.$route.params.id 拿到动态参数:

export default {
  created() {
    console.log('当前用户ID:', this.$route.params.id)
  }
}

③ 处理“参数变化但组件复用”的问题

如果从 /user/1 跳转到 /user/2,Vue 会复用 User 组件(因为是同一个组件实例),导致 created 等生命周期不触发,这时候要监听路由变化

watch 监听 $route

export default {
  watch: {
    '$route'(to, from) {
      // to 是目标路由,from 是来源路由
      console.log('参数从', from.params.id, '变成', to.params.id)
      this.fetchUser(to.params.id) // 重新请求用户数据
    }
  }
}

用组件内守卫 beforeRouteUpdate

export default {
  beforeRouteUpdate(to, from, next) {
    this.fetchUser(to.params.id)
    next() // 必须调用 next() 继续跳转
  }
}

场景举例:电商平台的商品详情页,不同商品 ID 对应同一个组件,需要根据 ID 变化重新请求数据,这时候动态路由+参数监听就派上用场。

嵌套路由怎么实现“页面里套页面”的结构?

很多项目需要“父页面包含子页面”,比如后台管理系统的“侧边栏+主内容区”:点击侧边栏菜单,主内容区切换不同子页面,这时候用嵌套路由

① 规划路由结构(以后台为例)

父路由:/admin(对应布局组件 AdminLayout,包含侧边栏和子路由出口)
子路由:/admin/posts(文章管理)、/admin/categories(分类管理)

② 配置嵌套路由规则

router.js 里,给父路由加 children 数组:

{
  path: '/admin',
  component: AdminLayout, // 父组件:包含侧边栏和 <router-view>
  children: [
    { path: 'posts', component: PostManage }, // 子路由,path 不加 /
    { path: 'categories', component: CategoryManage }
  ]
}

③ 父组件里放子路由出口

AdminLayout.vue 的模板中,除了侧边栏,还要有 <router-view> 作为子路由的挂载点:

<template>
  <div class="admin-layout">
    <!-- 侧边栏 -->
    <aside>
      <router-link to="/admin/posts">文章管理</router-link>
      <router-link to="/admin/categories">分类管理</router-link>
    </aside>
    <!-- 子路由出口:子组件会渲染到这里 -->
    <router-view></router-view>
  </div>
</template>

现在访问 /admin/posts 时,PostManage 组件会渲染到 AdminLayout<router-view> 里,实现“页面嵌套页面”的效果。

路由传参有哪几种方式?各自适合啥场景?

路由传参有 3 种主流方式,核心差异是参数存储位置组件解耦程度

① query 传参:“挂在 URL 问号后”

跳转时用 query 字段,参数会出现在 URL 的 后(如 /search?keyword=Vue)。

跳转方式

// 字符串路径
this.$router.push('/search?keyword=Vue')
// 对象形式(推荐,配合 name 更可靠)
this.$router.push({
  name: 'Search', // 路由规则里的 name(可选,但更稳定)
  query: { keyword: 'Vue' }
})

组件内获取

export default {
  created() {
    console.log('搜索关键词:', this.$route.query.keyword)
  }
}

适合场景:非关键参数、需要“刷新页面后参数保留”“支持 URL 分享”的场景(如搜索页关键词、列表分页)。

② params 传参:“藏在动态路由里”

参数通过动态路由的 参数名 传递,必须在路由规则里定义。

配置路由规则

{ path: '/user/:id', name: 'User', component: User }

跳转方式

this.$router.push({
  name: 'User', // 必须用 name(用 path 传 params 会丢失)
  params: { id: 123 }
})

组件内获取

export default {
  created() {
    console.log('用户ID:', this.$route.params.id)
  }
}

注意:如果路由规则没定义 id,直接用 params 传参会导致参数丢失(刷新页面后 params 也会消失)。

适合场景:路径必须包含的“关键标识”(如用户 ID、文章 ID),且不需要 URL 显式暴露参数(但动态路由的参数其实会显式在 URL 里)。

③ props 传参:“让组件更纯”

把路由参数当作组件的 props 传递,减少组件对 $route 的依赖,更易复用和测试。

配置路由规则:在路由里开启 props: true(或函数形式自定义传参):

{ path: '/user/:id', component: User, props: true }

组件内接收:用 props 声明参数:

export default {
  props: ['id'], // 直接接收路由参数作为 props
  created() {
    console.log('用户ID:', this.id)
  }
}

适合场景:需要“组件解耦”的场景(比如组件要做单元测试,不想依赖 $route),或参数需要二次处理(用函数形式传参)。

搜索页用 query(方便分享),详情页用 params(路径必须带 ID),公共组件用 props(解耦好维护)。

导航守卫怎么控制页面权限和跳转逻辑?

导航守卫是“路由跳转的生命周期钩子”,能在跳转前、跳转中、跳转后做逻辑处理(比如权限判断、数据预加载),分 3 类:

① 全局守卫:router.beforeEach(全局生效)

router.js 里配置,对所有路由跳转生效。典型场景:登录拦截

示例:拦截需要登录的页面

router.beforeEach((to, from, next) => {
  // to:目标路由;from:来源路由;next:必须调用才会继续跳转
  const requiresAuth = to.meta.requiresAuth // 路由元信息标记是否需要登录
  const isLogin = localStorage.getItem('token') // 假设用 localStorage 存 token
  if (requiresAuth && !isLogin) {
    next('/login') // 没登录,跳转到登录页
  } else {
    next() // 允许跳转
  }
})

然后在需要登录的路由里加 meta

{ 
  path: '/admin', 
  component: AdminLayout, 
  meta: { requiresAuth: true } // 标记需要登录
}

② 路由独享守卫:beforeEnter(只对当前路由生效)

在单个路由规则里配置,仅对当前路由的跳转生效。典型场景:付费内容拦截

示例:拦截未购买的付费课程页面

{
  path: '/course/premium',
  component: PremiumCourse,
  beforeEnter: (to, from, next) => {
    const isPurchased = localStorage.getItem('purchased')
    if (!isPurchased) {
      next('/course/buy') // 没购买,跳转到购买页
    } else {
      next()
    }
  }
}

③ 组件内守卫:beforeRouteEnter / beforeRouteUpdate / beforeRouteLeave

在组件内部定义,对当前组件的路由跳转生效。典型场景:表单离开提示、参数变化处理

示例:离开编辑页时提示保存

export default {
  data() {
    return { formChanged: false }
  },
  beforeRouteLeave(to, from, next) {
    if (this.formChanged) {
      const confirm = window.confirm('表单有修改,是否保存?')
      if (confirm) {
        this.saveForm()
        next()
      } else {
        next(false) // 取消跳转
      }
    } else {
      next()
    }
  }
}

导航守卫的核心是控制跳转流程,通过 next() 的参数(如 next('/login')next(false))决定是否允许跳转、跳转到哪。

路由懒加载怎么优化项目性能?

传统路由写法是“先 import 所有组件,再打包”,会导致首屏加载一个超大 JS 文件。路由懒加载能把组件分成多个小文件,访问对应路径时再加载,减少首屏压力。

① 懒加载写法:用动态 import()

router.js 里的组件导入改成动态导入:

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

这样打包后,HomeAbout 会变成两个独立的 JS 文件(chunk),只有访问对应路径时才会加载。

② 进阶:给 chunk 命名(webpack 魔法注释)

为了方便调试,给每个 chunk 起名字:

const Home = () => import(/* webpackChunkName: "home" */ './views/Home.vue')
const About = () => import(/* webpackChunkName: "about" */ './views/About.vue')

打包后,文件会变成 home.jsabout.js,更易识别。

适合场景:页面多、组件体积大的项目(如后台系统有几十个页面),首屏只加载首页,其他页面按需加载,能大幅减少首屏加载时间。

vue-router 3.6 和 Vue3 能一起用吗?是否要升级到 4.x?

一句话总结版本对应:

  • vue-router 3.x → 只能搭配 Vue2
  • vue-router 4.x → 只能搭配 Vue3
  • 如果你项目是 Vue2 技术栈,继续用 3.6 完全没问题,生态成熟、文档丰富;
  • 如果你要升级到 Vue3,必须把 vue-router 也升级到 4.x,同时要改代码:
功能 vue-router 3.x vue-router 4.x
路由实例创建 new VueRouter({ routes }) createRouter({ history, routes })
路由模式 mode: 'history' history: createWebHistory()
组件内使用 this.$router / this.$route useRouter() / useRoute()(组合式 API)

升级建议:小项目可直接升级 Vue3 + vue-router 4.x;大项目要评估改动成本,可先做技术调研再推进。

路由开发中常见问题怎么解决?

开发时遇到路由不生效、跳转报错、参数丢了…别慌,按场景排查:

① 路由不生效:页面一直空白

  • 检查 router 是否注入到 Vue 根实例(main.js 里有没有 router 选项);
  • 检查 routes 配置:path 有没有拼写错,component 路径是否正确(特别是懒加载时的路径);
  • 检查 <router-view> 是否在 App.vue 或父组件里正确放置(没放的话,匹配的组件没地方渲染)。

② 跳转报错:NavigationDuplicated

6 版本重复跳转到同一路径(如连续点击同一个 <router-link>)会报错,解决方法:全局捕获错误

router.js 里加这段代码:

const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location) {
  return originalPush.call(this, location).catch(err => err)
}

③ 参数获取不到:$route.params / $route.query 是空的

  • 如果是 params:检查路由规则是否定义了动态段(如 id),且跳转时用了 name(用 pathparams 会丢失);
  • 如果是 query:检查跳转时是否用了 query 字段,且 URL 里确实有 ?xxx=yyy

④ 嵌套路由不显示:子

版权声明

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

热门