1.最基础的页面跳转,有哪两种核心实现方式?
不少刚接触Vue3项目的同学,一碰到页面跳转就犯难——明明装了router,点击按钮咋没反应?编程式和声明式跳转有啥区别?传参后页面刷新数据丢了咋整?今天就把Vue3 Router跳转的常见场景、实现方法和避坑技巧一次性讲明白,从基础到进阶帮你理顺逻辑~
Vue3 Router里实现页面跳转,核心是**声明式**和**编程式**这两种方式,理解它们的区别和适用场景,能少走很多弯路。先看声明式跳转,靠<router-link>组件实现,它有点像HTML里的<a>标签,但会自动处理路由激活状态、避免页面全刷,用法分两种:
- 简单字符串路径:
<router-link to="/about">去关于页</router-link>,点击后URL会变成/about,对应组件渲染到<router-view>里。 - 动态传参/路径对象:如果要传查询参数或用命名路由,写成对象更灵活,比如
<router-link :to="{ name: 'Article', params: { id: 1 } }">看文章</router-link>(这里name要和路由配置里的name对应)。
再讲编程式跳转,适合按钮点击、逻辑判断后跳转(比如登录成功跳首页),步骤是先通过useRouter拿到路由实例,再调用跳转方法:
<script setup>
import { useRouter } from 'vue-router'
const router = useRouter()
// 基础跳转:push是“新增历史记录”
const goHome = () => {
router.push('/home')
}
// 回退上一页(类似浏览器后退)
const goBack = () => {
router.go(-1)
}
</script>
简单总结:导航栏、菜单这类“静态跳转入口”用声明式,逻辑里的跳转(比如表单提交后)用编程式。
跳转时需要传参数,query和params该怎么选?
开发中跳转几乎都要传数据(比如商品ID、搜索关键词),但query和params很容易搞混,先看语法差异:
(1)query传参:“路径后挂参数,刷新不丢数据”
query是把参数拼在URL里(类似?keyword=Vue3),不管路由有没有定义动态参数,都能传,跳转时用对象写法:
// 编程式
router.push({
path: '/search',
query: { keyword: 'Vue3', page: 1 }
})
// 声明式
<router-link :to="{ path: '/search', query: { keyword: 'Vue3' }}">搜索</router-link>
接收参数时,用useRoute拿到路由实例,读route.query:
<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
console.log(route.query.keyword) // 输出 "Vue3"
</script>
优点是刷新页面参数还在(因为URL里能看到),缺点是参数暴露在URL,不太适合敏感信息。
(2)params传参:“依赖命名路由,动态路由才稳”
params是给命名路由传“隐藏参数”,但有个大坑:如果路由没配置动态参数(比如path: '/product/:id'),刷新页面后params会丢失!
正确用法分两步:
① 路由配置里定义动态参数(必须):
const routes = [
{
path: '/product/:id', // 动态段:id
name: 'Product',
component: Product
}
]
② 跳转时用name匹配路由,传params:
router.push({
name: 'Product',
params: { id: 123 }
})
接收参数同样用route.params.id。
如果路由没配动态参数(比如path: '/product'),强行用params传参,URL不会变化,刷新后参数直接没了,所以params适合和动态路由结合,让参数成为URL的一部分,这样刷新也不会丢;如果想传“临时参数”且不怕暴露,优先用query。
登录页、权限页这些需要“拦截”的场景,咋用导航守卫控制跳转?
很多页面需要权限(我的订单”必须登录才能进),这时候导航守卫看门人”——在跳转前判断权限,决定放行、拦截或重定向。
Vue3 Router的导航守卫分三类,核心记住全局前置守卫(最常用):
(1)全局前置守卫:router.beforeEach
在路由实例创建后,用beforeEach拦截所有跳转,逻辑写在路由配置文件里:
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({ ... })
// 模拟判断是否登录(实际项目里可能是store里的状态)
const isLogin = () => {
return localStorage.getItem('token') !== null
}
router.beforeEach((to, from, next) => {
// 如果目标页面需要权限,且没登录 → 跳登录页
if (to.meta.requiresAuth && !isLogin()) {
next('/login')
} else {
next() // 放行
}
})
这里to是“要跳转到的目标路由”,from是“从哪个路由来”,next是“决定下一步干啥”。
(2)路由独享守卫:beforeEnter
如果只有某几个路由需要权限,不用全局守卫,给单个路由加beforeEnter:
const routes = [
{
path: '/order',
component: Order,
meta: { requiresAuth: true },
beforeEnter: (to, from, next) => {
if (!isLogin()) next('/login')
else next()
}
}
]
(3)组件内守卫:onBeforeRouteUpdate
如果组件复用(比如动态路由的商品详情页,从/product/1跳到/product/2,组件没销毁),需要监听路由变化,用onBeforeRouteUpdate:
<script setup>
import { onBeforeRouteUpdate } from 'vue-router'
import { useRoute } from 'vue-router'
const route = useRoute()
// 初始加载时获取数据(比如从route.params.id拿ID)
const loadData = (id) => { ... }
loadData(route.params.id)
// 路由变化时(比如从/product/1 → /product/2),重新加载数据
onBeforeRouteUpdate((to, from) => {
loadData(to.params.id)
})
</script>
守卫的核心逻辑是:在跳转前做权限判断、数据加载、埋点统计,灵活组合三类守卫能覆盖90%的权限场景。
商品详情、用户个人页这类动态路由,跳转时要注意什么?
动态路由(比如/product/:id)是实现“一个组件复用,渲染不同数据”的关键,但跳转和传参容易踩坑,重点看这两点:
(1)动态路由的配置与匹配
路由配置必须包含动态段(比如:id),否则params传参刷新会丢(前面讲过),配置示例:
const routes = [
{
path: '/product/:id', // 动态段:id
name: 'Product',
component: Product,
// 也可以给动态段加正则约束(比如ID必须是数字)
pathToRegexpOptions: { strict: true }
}
]
(2)嵌套路由的跳转逻辑
如果项目有“父页面套子页面”(比如/user下有/user/profile和/user/order),路由要配children:
const routes = [
{
path: '/user',
component: UserLayout, // 父组件,包含<router-view>渲染子组件
children: [
{ path: 'profile', component: UserProfile }, // 子路由,路径是/user/profile
{ path: 'order', component: UserOrder }
]
}
]
跳转子路由时,路径要写全(比如/user/profile),或者用命名路由:
<!-- 声明式 -->
<router-link to="/user/profile">个人信息</router-link>
<!-- 编程式 -->
router.push({ name: 'UserProfile' }) // 假设子路由配了name
注意:父组件必须包含<router-view>,否则子组件没地方渲染;子路由的path不要加斜杠(比如不能写/profile,否则路径会变成/profile,脱离父路由)。
router.push和router.replace有啥区别?哪些场景用replace更合适?
router.push和router.replace都是编程式跳转,但历史记录的处理完全不同:
router.push('/path'):在历史记录里新增一条记录,用户点浏览器后退能回到上一页。router.replace('/path'):把当前历史记录替换成新路径,用户点后退不会回到当前页(因为记录被替换了)。
举个场景例子:
- 登录页 → 首页:用
push,用户后退能回到登录页(合理)。 - 支付成功页 → 订单列表:用
replace,因为支付成功后不希望用户回退到支付页(防止重复提交)。
代码里区别只在方法名:
// 新增记录(后退能回到当前页)
router.push('/success')
// 替换记录(后退跳转到更前的页面)
router.replace('/success')
用户输错路径出现404,咋配置兜底的跳转页面?
项目里肯定要处理“用户输错URL”的情况,这时候需要兜底路由(404页面),配置要点:
① 新建404组件(比如NotFound.vue),写好提示内容。
② 路由配置里,把404路由放在最后一位(因为Vue Router是“先匹配优先”):
const routes = [
{ path: '/home', component: Home },
{ path: '/about', component: About },
// 其他路由...
{ path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound }
]
这里path: '/:pathMatch(.*)*'是Vue3的写法,匹配所有未定义的路径(包括多级路径,比如/user/123/abc)。
这样用户访问/xxx或/user/unknown时,就会跳转到404组件。
移动端做页面切换动画,路由跳转咋和过渡效果结合?
移动端App常见“页面滑动切换”动画,Vue3里可以用<transition>组件包裹<router-view>,结合CSS实现过渡。
步骤:
① 在App.vue(或路由出口的父组件)里,用<transition>包裹<router-view>,并设置过渡名:
<template>
<transition name="slide-fade">
<router-view></router-view>
</transition>
</template>
<style>
.slide-fade-enter-from {
opacity: 0;
transform: translateX(100%);
}
.slide-fade-enter-to {
opacity: 1;
transform: translateX(0);
}
.slide-fade-enter-active {
transition: all 0.3s ease;
}
/* 离开时的动画(可选) */
.slide-fade-leave-from {
opacity: 1;
}
.slide-fade-leave-to {
opacity: 0;
transform: translateX(-100%);
}
.slide-fade-leave-active {
transition: all 0.3s ease;
}
</style>
② 这样每次路由跳转,组件都会触发进入/离开动画,如果想区分“前进/后退”用不同动画,可以结合router-view的v-slot获取路由方向,或者用第三方库(比如vue-router-transition)。
也可以结合Animate.css这类动画库,简化CSS:
<transition name="animate__animated animate__fadeIn"> <router-view></router-view> </transition>
(需要先安装Animate.css并全局引入)
用Nuxt3做SSR时,路由跳转有啥特殊处理?
如果项目用Nuxt3(Vue3的服务端渲染框架),路由跳转要考虑服务端和客户端的同步,Nuxt3自动生成路由,但编程式跳转和Vue3有细微区别:
- 客户端跳转:用
useRouter的push/replace,和Vue3一致。 - 服务端跳转:在服务端逻辑(比如中间件、页面加载函数)里,不能直接用
router.push,要结合navigateTo方法:// 服务端/客户端通用的跳转 const navigateTo = useNavigate() navigateTo('/home')
Nuxt3的路由是文件系统驱动(pages目录下的文件即路由),动态路由用_id.vue命名(比如pages/product/_id.vue对应/product/:id),跳转时传参更简洁:
// 编程式跳转动态路由
navigateTo(`/product/${productId}`)
SSR场景下要确保路由数据和页面渲染同步,避免“客户端 hydration 错误”,这部分需要结合Nuxt3的生命周期钩子(比如onServerPrefetch)处理数据预取,但核心跳转逻辑和Vue3 Router是一脉相承的。
最后总结一下,Vue3 Router跳转的核心是“选对方式+处理参数+控制权限+兼容场景”,声明式和编程式各有适用场景,传参要分清query/params的差异,导航守卫搞定权限,动态路由和嵌套路由注意配置细节,再结合动画、404、SSR这些场景优化,就能把路由跳转玩得很顺~
如果还有具体场景没覆盖到,多标签页应用的路由同步”“Electron桌面端的路由处理”,可以留言讨论,下次单独拆解~
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
code前端网



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