1.啥是 vue-router?它在 Vue 项目里有啥用?
想搞懂 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
- 先装依赖:终端执行
npm install vue-router@4
(Vue3 用 v4,Vue2 用 v3,注意版本匹配); - 在
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
- 在
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前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。