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

1.最基础的页面跳转,有哪两种核心实现方式?

terry 2周前 (10-01) 阅读数 44 #Vue

不少刚接触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、搜索关键词),但queryparams很容易搞混,先看语法差异

(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.pushrouter.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-viewv-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有细微区别:

  • 客户端跳转:用useRouterpush/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前端网发表,如需转载,请注明页面地址。

发表评论:

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

热门