1.vue-router.js 到底是个啥工具?
前端开发里,Vue.js 生态的路由工具 vue-router.js 算是“必学技能”,但不少刚入门的同学总会犯懵:它到底是干啥的?咋在项目里用?遇到路由跳转失效、页面不更新这些问题咋解决?今天咱就用问答形式,把 vue-router 的关键知识点和开发坑点一次性讲清楚~
简单说,vue-router 是 Vue 官方出的路由管理器,专门帮单页应用(SPA)实现“无刷新页面跳转”和“组件切换”。
举个现实例子:传统多页网站点“首页”“,浏览器会整页刷新换内容;但 SPA (比如用 Vue 做的后台管理系统)点导航时,页面不刷新,只是局部换组件,vue-router 就是背后的“导航指挥官”——它决定哪个路径对应哪个组件,还能管理导航过程(比如权限验证、传参)。
要是没它,你得自己写代码监听 URL 变化、手动切换组件,不仅麻烦还容易搞出 bug,所以做中大型 Vue 项目,vue-router 几乎是标配。
为啥做 SPA 必须得用 vue-router?自己写路由不行吗?
不是不能自己写,但vue-router 把路由逻辑封装得特别顺手,省了超多重复劳动,它至少解决了这几个核心问题:
- 声明式导航:用
<router-link>
组件写导航,不用手动写window.location
,还能自动处理“当前页面高亮”这类样式逻辑; - 编程式导航:在 JS 里用
this.$router.push()
跳转,比如登录成功后跳首页,逻辑里调一行代码就搞定; - 路由嵌套:像后台系统的“布局页 + 子页面”结构(比如侧边栏固定,中间内容换),用路由嵌套能少写很多重复代码;
- 参数传递 & 权限控制:动态路由传参(
/user/123
)、查询参数(?id=123
)、路由守卫(跳转前验权)这些功能,自己实现得写一堆判断逻辑,vue-router 直接给现成 API;
要是硬自己写,光处理“URL 变化但页面不刷新”“组件复用导致数据不更新”这些细节,就能把人折腾疯,所以除非做极简单的 Demo,否则直接用官方路由更高效。
vue-router 基础使用步骤是啥样的?(拿小项目举例子)
咱以“做个有首页和关于页的小 SPA”为例,走一遍流程:
步骤 1:安装 vue-router
如果是 Vue2 项目,用 npm install vue-router@3
;Vue3 项目则用 npm install vue-router@4
(版本差异后面讲),也可以用 CDN 直接引入,但项目里一般用包管理工具。
步骤 2:配置路由规则
新建个 router
文件夹,里面建 index.js
,写路由规则:
// Vue2 版本示例
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '@/components/Home.vue'
import About from '@/components/About.vue'
Vue.use(VueRouter) // 注册路由插件
const routes = [
{ path: '/', component: Home }, // 根路径对应 Home 组件
{ path: '/about', component: About } // /about 对应 About 组件
]
const router = new VueRouter({
routes // 把规则传给路由实例
})
export default router
(Vue3 版本写法不同,后面“Vue3 配合”部分详细说)
步骤 3:把路由注入 Vue 根实例
打开项目入口文件 main.js
,把路由实例挂到 Vue 上:
// Vue2 示例
import Vue from 'vue'
import App from './App.vue'
import router from './router' // 引入上面写的路由配置
new Vue({
router, // 注入路由
render: h => h(App)
}).$mount('#app')
步骤 4:在页面里用路由组件
在 App.vue
这类根组件里,用 <router-link>
做导航,用 <router-view>
显示匹配的组件:
<template>
<div id="app">
<!-- 声明式导航:点“首页”跳 /,点“跳 /about -->
<router-link to="/">首页</router-link>
<router-link to="/about">lt;/router-link>
<!-- 匹配到的组件会渲染到这里 -->
<router-view></router-view>
</div>
</template>
这样一配,点导航时页面就会无刷新切换组件啦~
路由传参有哪几种方式?分别适合啥场景?
开发里经常需要“跳转时带数据”,比如从列表页点用户头像,跳转到用户详情页并传用户 ID,vue-router 有三种常用传参方式,各有适用场景:
方式 1:动态路由(用 params 传参)
配置路由时,路径里加动态段,path: '/user/:id'
;跳转时用 <router-link to="/user/123">
或者 this.$router.push('/user/123')
;组件里用 this.$route.params.id
取参数。
适合场景:参数是“资源唯一标识”(比如用户 ID、商品 ID),且希望参数显示在 URL 里(刷新页面参数不会丢),像电商详情页 /goods/1001
这种场景常用。
方式 2:查询参数(用 query 传参)
配置路由时路径正常写(path: '/user'
),跳转时带查询参数,像 <router-link to="/user?id=123">
或者 this.$router.push({ path: '/user', query: { id: 123 } })
;组件里用 this.$route.query.id
取参数。
适合场景:参数不是核心标识(比如搜索页的关键词、分页页码),或者需要传多个非关键参数,URL 里会显示 ?id=123&page=2
这类结构,刷新也能保留。
方式 3:路由元信息(meta 传参)
配置路由时,给路由对象加 meta
字段,
{
path: '/admin',
component: Admin,
meta: { requiresAuth: true, title: '后台管理' }
}
组件里用 this.$route.meta.requiresAuth
取配置;也能在路由守卫里用(比如判断是否需要登录)。
适合场景:给“页面级别”加配置信息(比如是否需要权限、页面标题),这些信息不需要显示在 URL 里,只在代码里判断用。
总结下:要让参数在 URL 里、当资源标识用 params;要传多个非关键参数、URL 可带?用 query;要给页面加配置用 meta。
路由嵌套是咋实现的?实际项目哪块会用到?
路由嵌套指的是“一个页面里包含子页面”,典型场景是后台管理系统的布局页——比如侧边栏和顶栏是固定的,中间内容区根据不同路由显示不同子页面(仪表盘、用户管理、订单管理等)。
实现分两步:
步骤 1:配置嵌套路由规则
在父路由的 children
数组里写子路由,
const routes = [
{
path: '/dashboard',
component: DashboardLayout, // 父组件(包含侧边栏、顶栏)
children: [
{ path: 'home', component: DashboardHome }, // 子路由,路径是 /dashboard/home
{ path: 'stats', component: DashboardStats } // 子路由,路径是 /dashboard/stats
]
}
]
步骤 2:父组件模板里加 <router-view>
在 DashboardLayout.vue
里,侧边栏和顶栏代码之外,留个 <router-view>
给子组件:
<template>
<div class="dashboard-layout">
<aside>侧边栏</aside>
<header>顶栏</header>
<main>
<!-- 子组件会渲染到这里 -->
<router-view></router-view>
</main>
</div>
</template>
这样访问 /dashboard/home
时,DashboardLayout
会渲染,中间 <router-view>
显示 DashboardHome
组件,实际项目里,只要有“公共布局 + 多个子页面”的结构,都适合用路由嵌套,能少写很多重复的布局代码。
声明式导航和编程式导航有啥区别?该咋选?
vue-router 提供了两种导航方式,核心区别是“在哪写导航逻辑”:
声明式导航:用 <router-link>
组件
直接在模板里写,
<router-link to="/home">回首页</router-link>
优点:简单直观,vue-router 会自动把它渲染成 <a>
标签,还能自动处理“当前页面高亮”(通过 active-class
属性);
适合场景:导航栏、菜单按钮这些“模板里能看到的导航”,比如页面顶部的 Tab 栏、侧边栏菜单。
编程式导航:用 this.$router.push()
等方法
在 JS 逻辑里写,比如登录成功后跳转:
methods: {
handleLogin() {
// 登录逻辑...
this.$router.push('/home') // 登录成功后跳转到首页
}
}
优点:灵活,能在任意 JS 逻辑里触发导航(Ajax 回调、定时器里);
适合场景:需要“逻辑判断后再跳转”的情况,比如登录校验、表单提交成功后跳转。
模板里能写死的导航用声明式,逻辑里动态判断的导航用编程式。
路由守卫是干啥的?咋用它做权限控制?
路由守卫可以理解成“路由跳转过程中的钩子函数”,能在“跳转前、跳转后、组件复用前”这些时机插逻辑,最常用的场景是权限控制(比如判断用户是否登录,没登录就拦截到登录页)。
vue-router 有三类守卫,咱重点讲全局守卫(控制所有路由)和路由独享守卫(控制单个路由):
全局守卫:router.beforeEach
在路由配置文件里,给 router 实例加全局前置守卫:
router.beforeEach((to, from, next) => {
// to:要跳转到的目标路由对象
// from:从哪个路由跳过来的
// next:放行函数,必须调用才能继续跳转
if (to.meta.requiresAuth) { // 检查目标路由是否需要权限
if (isLogin()) { // 假设 isLogin() 是判断登录状态的函数
next() // 已登录,放行
} else {
next('/login') // 没登录,跳转到登录页
}
} else {
next() // 不需要权限,直接放行
}
})
这样,所有配置了 meta: { requiresAuth: true }
的路由,都会被拦截验权。
路由独享守卫:beforeEnter
给单个路由加守卫,只控制这一个路由:
const routes = [
{
path: '/admin',
component: Admin,
meta: { requiresAuth: true },
beforeEnter: (to, from, next) => {
// 逻辑和全局守卫类似,只作用于这个路由
if (isLogin()) {
next()
} else {
next('/login')
}
}
}
]
权限控制思路:给需要权限的路由加 meta.requiresAuth = true
,然后用全局守卫统一拦截,判断用户登录状态,没登录就跳登录页,这样一套下来,就能实现“未登录用户进不去后台页面”的效果。
开发时遇到“路由跳转后页面不更新”咋解决?
这问题特常见,原因是路由参数变了,但组件被复用了——比如从 /user/1
跳到 /user/2
,Vue 为了性能,会复用同一个 User 组件实例,导致 created
、mounted
这些生命周期钩子不重新执行,数据也就不更新。
解决方法有三种,按需选:
方法 1:监听 $route 变化
在组件里用 watch
监听 $route
的变化,参数变了就重新请求数据:
export default {
watch: {
$route(to, from) {
// to 是新路由,from 是旧路由
this.fetchUserData(to.params.id) // 重新调接口拿新数据
}
},
methods: {
fetchUserData(id) { ... }
}
}
方法 2:给 <router-view> 加 key
在父组件的 <router-view>
上加 key
,值设为 $route.fullPath
(完整 URL),这样 URL 变了,key 也变,Vue 会认为组件需要重新渲染:
<router-view :key="$route.fullPath"></router-view>
方法 3:用组件内守卫 beforeRouteUpdate
在组件里写 beforeRouteUpdate
守卫,参数变化时执行逻辑:
export default {
beforeRouteUpdate(to, from, next) {
// 路由更新前,拿到新参数
this.userId = to.params.id
this.fetchUserData(this.userId)
next() // 必须调用 next 放行
}
}
这三种方法都能解决“组件复用导致数据不更新”的问题,选哪种看项目习惯,监听 $route
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。