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前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。