Vue3页面跳转到底该怎么选?从入门到进阶避坑指南
刚接触Vue3的新手经常会在打开新页面或者切换视图时犯愁:一会儿看到router-link,一会儿碰到push/replace,还有原生的window.location甚至a标签?到底哪种才是“正确打开方式”?其实这些跳转方式各有用途,选错不仅可能拖慢页面加载,还会触发不必要的组件重新渲染,今天咱们就从实际场景出发,把这几种方式掰扯清楚,连避坑细节也一起说透。
先理清大前提:你用的是单页应用还是多页应用
很多新手跳坑的第一步,就是没搞清楚自己的项目是SPA(单页应用)还是MPA(多页应用),目前主流的Vue3项目,不管是用Vite还是Vue CLI默认创建的,都是单页应用——整个项目只有一个HTML入口文件,页面切换其实是在这个入口里动态替换DOM组件,浏览器不会重新加载整个页面,这也是Vue路由(Vue Router)存在的核心意义。
那什么时候会出现多页应用?比如你有一个Vue3写的后台管理系统,旁边挂了一个完全独立的用原生HTML做的帮助文档,或者某个模块需要和其他技术栈(比如React或者WordPress)的页面无缝对接,这时候才会用到跨页面的原生跳转。
第一个核心判断标准就是:目标页面是不是当前Vue3项目里注册过的路由? 如果是,优先用Vue Router的API或者组件;如果不是,才考虑原生跳转。
Vue3单页应用内的首选:Vue Router
既然是单页应用,Vue Router肯定是官方钦定、最适配的跳转方案,它有两种常用的实现方式:声明式跳转(用router-link组件)和编程式跳转(用useRouter组合式API的push/replace方法),下面分别说。
什么时候用声明式的router-link
当跳转逻辑是“用户点击某个元素,然后直接跳转”时,就用router-link,比如导航栏的菜单按钮、文章列表的标题链接、商品卡片的跳转入口,这些场景下不需要写额外的JS逻辑,用router-link既简单又能自动处理很多细节。
router-link本质上是对原生a标签的封装,它会自动根据你的路由模式(hash或者history)生成对应的href属性,浏览器鼠标悬停时也会显示正确的链接地址,对SEO(搜索引擎优化)和无障碍访问都很友好——这一点比纯用JS绑定click事件调用push要好很多,很多新手容易忽略这个SEO细节。
不过用router-link也有几个避坑点:
- 别随便加target="_blank":如果非要打开新标签页,记得加上rel="noopener noreferrer",防止新页面通过window.opener访问原页面的DOM,带来安全隐患;
- 嵌套路由要注意active-class的匹配:比如你有一个父路由“/user”,子路由“/user/profile”,当访问子路由时,父路由的router-link也会默认加上router-link-active这个高亮类,如果不想让父路由跟着亮,可以改成router-link-exact-active,或者自定义exact属性;
- 传递参数时尽量不用字符串拼接:虽然可以写成
<router-link to="/user/123"></router-link>,但更推荐用对象的方式,比如<router-link :to="{ name: 'User', params: { id: 123 } }"></router-link>,这样如果以后修改了路由的path,只需要改路由配置文件就行,不需要去改所有用到这个链接的地方,维护成本低很多。
什么时候用编程式的useRouter
如果跳转逻辑不是“点了就走”,而是需要先做一些前置操作,那就要用useRouter了,比如登录之后跳转到首页、提交表单成功后跳转到结果页、根据用户权限判断是否允许跳转(这时候还要配合路由守卫)、倒计时结束后自动跳转等等。
useRouter是Vue3组合式API里的写法,替代了Vue2里的this.$router,使用之前记得先从vue-router里引入:
import { useRouter } from 'vue-router'
export default {
setup() {
const router = useRouter()
// 跳转逻辑在这里写
}
}
编程式跳转主要有两个方法:push和replace,很多人搞不清它们的区别,其实核心就是浏览器历史记录的处理方式。
- push:会在浏览器的历史记录里新增一条记录,用户点击“返回”按钮时,会回到上一个页面;
- replace:不会新增历史记录,而是直接替换当前页面的记录,用户点击“返回”按钮时,会回到上上一个页面。
那什么时候用replace?比如登录成功后,肯定不想让用户点返回又回到登录页吧?这时候就用replace;还有填写表单的中间页,比如从A到B再到C,提交C成功后回到A,这时候B到C也可以用replace,这样用户从C点返回直接到A。
编程式跳转传递参数的方式和router-link类似,也是推荐用对象+name+params,不过这里有个超级重要的避坑点:Vue Router 4.x(也就是Vue3配套的版本)里,params参数只有在跳转到命名路由时才会生效,而且如果用户刷新页面,params参数会丢失!如果需要刷新页面后参数还在,要么用query参数,要么把参数存在localStorage/sessionStorage里,要么用动态路由(也就是path里带/:id这种占位符的路由),比如刚才的例子,如果你把路由配置成:
const routes = [
{
path: '/user/:id',
name: 'User',
component: () => import('../views/User.vue')
}
]
那用params传的id会自动出现在URL里,刷新页面也不会丢;但如果path是‘/user’,没有占位符,刷新后params就没了。
还有query参数,不管是用push/replace还是router-link,不管跳转到命名路由还是path路由,都可以用,而且会自动拼在URL后面(user?id=123),刷新后也不会丢,适合传递一些非敏感的、可选的参数,比如搜索关键词、分页页码。
什么时候用原生跳转方式?
刚才说了,当目标页面不是当前Vue3项目里的路由时,就用原生跳转,原生跳转主要有两种:a标签和window.location。
什么时候用原生a标签
原生a标签的使用场景和router-link有点像,但它是用来跳转外部页面的,比如跳转到百度、跳转到微信的授权页面、跳转到其他技术栈的页面,原生a标签会让浏览器重新加载整个页面,性能会比单页应用的切换慢一点,但跨页面跳转没办法,只能用这个。
同样,用原生a标签打开新标签页时,也要加rel="noopener noreferrer",安全第一。
什么时候用window.location
和useRouter类似,当跳转外部页面需要前置操作时,就用window.location,比如你需要先统计一下用户点击外部链接的次数,然后再跳转,这时候就可以在JS里写window.location.href = 'https://www.baidu.com'。
window.location还有几个常用的属性和方法:
- window.location.href:当前页面的完整URL,赋值可以跳转;
- window.location.replace():和router.replace类似,替换当前历史记录;
- window.location.reload():刷新当前页面,加true参数可以强制刷新(不使用缓存);
- window.location.search:获取URL里的query参数部分(keyword=vue3)。
进阶用法:路由守卫配合跳转
刚才提了一句路由守卫,其实它也是页面跳转流程里的一部分,甚至可以说是进阶开发必备的技能,路由守卫的作用就是在跳转发生前、跳转发生中、跳转发生后,做一些拦截或者处理,比如判断用户有没有登录、有没有权限访问这个页面、页面跳转时要不要显示加载动画、要不要保存当前页面的滚动位置等等。
Vue Router 4.x里的路由守卫主要有三种:全局前置守卫、路由独享守卫、组件内守卫,咱们举个最常用的全局前置守卫的例子,比如判断用户有没有登录:
// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
import Login from '../views/Login.vue'
const routes = [
{ path: '/', name: 'Home', component: Home, meta: { requiresAuth: true } },
{ path: '/login', name: 'Login', component: Login }
]
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes
})
// 全局前置守卫
router.beforeEach((to, from, next) => {
// 从localStorage里获取token,模拟登录状态
const token = localStorage.getItem('token')
// 如果目标路由需要登录,且没有token,就跳转到登录页
if (to.meta.requiresAuth && !token) {
next({ name: 'Login' })
} else {
// 否则允许跳转
next()
}
})
export default router
这里的meta是路由元信息,是我们自定义的,可以用来存储路由的额外信息,比如是否需要登录、页面标题、权限标识等等,非常实用。
一张思维导图就能搞定的选择逻辑
最后咱们把刚才说的内容浓缩一下,方便大家快速判断:
- 先看目标页面是不是当前Vue3项目的路由?
- 是 → 用Vue Router
- 点击直接跳转,不需要前置逻辑 → 用router-link(加对象+name+params,加rel="_blank"的话别忘了noopener)
- 需要前置逻辑(登录、提交表单、倒计时) → 用useRouter
- 需要新增历史记录,用户能返回 → push
- 不需要新增历史记录,用户不能返回 → replace
- 刷新后参数不丢 → 用动态路由+params 或者 query
- 不是 → 用原生跳转
- 点击直接跳转 → 原生a标签(别忘noopener)
- 需要前置逻辑 → window.location
- 是 → 用Vue Router
这样是不是就清晰多了?新手刚学的时候别贪多,先把Vue Router的两种常用方式搞明白,把params和query的区别搞清楚,把刷新不丢参数的坑填上,然后再慢慢学路由守卫这些进阶内容,循序渐进,肯定能掌握好Vue3的页面跳转。
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
code前端网

