Vue3 中页面重定向主要依赖 Vue Router 4,这是一个Vue3 配套的路由库
具体分为「路由配置式重定向」「编程式导航重定向」「路由守卫重定向」三类场景,以下是各种方式汇总,欢迎补充
前置准备:确保 Vue Router 4 已安装
Vue3 必须使用 Vue Router 4(不兼容 Vue Router 3),如果没有,需要先安装依赖:
npm install vue-router@4
# 或 yarn add vue-router@4
基础路由实例配置(src/router/index.js)
import { createRouter, createWebHistory } from 'vue-router'
import Home from '@/views/Home.vue'
import Login from '@/views/Login.vue'
import Dashboard from '@/views/Dashboard.vue'
const routes = [
// 路由配置将在这里添加
]
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL), // History 模式(推荐)
// history: createWebHashHistory(), // Hash 模式(无需后端配置)
routes
})
export default router
在 main.js 中挂载路由:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
createApp(App).use(router).mount('#app')
二、核心重定向方式(按场景分)
1. 路由配置式重定向(初始化路由直接跳转)
场景 :进入某个路由时,无需组件渲染,直接自动跳转到目标路由(如默认首页、旧路径兼容)。实现方式 :在路由规则中通过 redirect 配置目标路径 / 路由名。
(1)基础写法:直接指定路径
const routes = [
// 访问根路径 "/" 时,重定向到 "/home"
{ path: '/', redirect: '/home' },
// 访问旧路径 "/old-login" 时,重定向到新路径 "/login"(兼容旧链接)
{ path: '/old-login', redirect: '/login' },
// 正常路由配置
{ path: '/home', component: Home },
{ path: '/login', component: Login }
]
(2)进阶写法:通过路由名重定向(更灵活)
先给目标路由设置 name,再通过 redirect: { name: '路由名' } 跳转,适合路径较长的场景:
const routes = [
{
path: '/',
redirect: { name: 'Home' } // 指向路由名 "Home"
},
{
path: '/home',
name: 'Home', // 定义路由名
component: Home
},
{
path: '/dashboard',
name: 'Dashboard',
component: Dashboard
}
]
(3)动态重定向:根据条件跳转
场景 :根据不同参数 / 状态,重定向到不同路由(如未登录跳登录,已登录跳首页)。实现方式 :redirect 接收函数,返回目标路由配置。
const routes = [
{
path: '/',
// 函数参数 to:当前访问的路由对象(含 params/query 等)
redirect: (to) => {
// 示例:根据本地存储判断登录状态
const isLogin = localStorage.getItem('token')
if (isLogin) {
return { name: 'Dashboard' } // 已登录跳控制台
} else {
return '/login' // 未登录跳登录页
}
}
},
{ path: '/login', component: Login },
{ path: '/dashboard', component: Dashboard }
]
2. 编程式导航重定向(组件内 / 逻辑中触发)
场景 :通过按钮点击、接口请求成功后等用户交互 / 逻辑触发跳转(如登录成功后跳首页、表单提交后跳结果页)。核心 API :通过 useRouter 钩子获取路由实例,调用 push 或 replace 方法。
(1)基础用法:组件内跳转(Composition API)
<!-- Login.vue -->
<template>
<div>
<h1>登录页</h1>
<button @click="handleLogin">登录</button>
</div>
</template>
<script setup>
import { useRouter } from 'vue-router'
const router = useRouter() // 获取路由实例
const handleLogin = async () => {
// 模拟登录接口请求
const loginSuccess = await mockLoginApi()
if (loginSuccess) {
// 方式1:跳转到路径(带 query 参数)
router.push('/dashboard?tab=1')
// 方式2:跳转到路由名(带 params 参数,需路由配置占位符)
// router.push({ name: 'Dashboard', params: { id: 1 }, query: { tab: 1 } })
// 方式3:replace 跳转(不添加历史记录,无法回退到当前页)
// router.replace('/dashboard')
}
}
// 模拟登录接口
const mockLoginApi = () => Promise.resolve(true)
</script>
(2)选项式 API 兼容写法(适用于旧项目迁移)
<script>
export default {
methods: {
handleLogin() {
this.$router.push('/dashboard') // 等同于 setup 中的 router.push
}
}
}
</script>
(3)关键区别:push vs replace
| 方法 | 行为描述 | 适用场景 |
|---|---|---|
router.push(path) |
添加新历史记录,可通过「回退」返回上一页 | 正常跳转(如列表页→详情页) |
router.replace(path) |
替换当前历史记录,无法回退到当前页 | 登录页、重定向页(避免回退到登录页) |
3. 路由守卫重定向(权限控制 / 全局拦截)
场景 :全局拦截所有路由跳转,根据条件重定向(如未登录拦截、角色权限控制、页面访问限制)。核心 API :Vue Router 4 的全局守卫(router.beforeEach)、路由独享守卫、组件内守卫。
(1)全局守卫:router.beforeEach(最常用)
在 router/index.js 中配置,拦截所有路由跳转,适合全局权限控制:
// router/index.js
router.beforeEach((to, from, next) => {
// to:即将跳转的目标路由
// from:当前离开的路由
// next:Vue Router 3 写法(Vue Router 4 可直接 return 路由对象,无需 next)
const token = localStorage.getItem('token') // 获取登录态
const whiteList = ['/login', '/register'] // 白名单(无需登录可访问)
// 逻辑:未登录且目标路由不在白名单 → 重定向到登录页
if (!token && !whiteList.includes(to.path)) {
// Vue Router 4 推荐写法:直接 return 目标路由
return { path: '/login', query: { redirect: to.path } }
// 携带 redirect 参数,登录成功后可跳回原目标页(见下文示例)
}
// 允许跳转(Vue Router 4 中可省略,默认放行)
return true
})
(2)登录成功后跳回原目标页(基于 redirect 参数)
在登录页处理 redirect 参数,实现「拦截后跳转回原页面」:
<!-- Login.vue -->
<script setup>
import { useRouter, useRoute } from 'vue-router'
const router = useRouter()
const route = useRoute() // 获取当前路由参数
const handleLogin = async () => {
const loginSuccess = await mockLoginApi()
if (loginSuccess) {
// 获取 redirect 参数(若有则跳回原页面,无则跳首页)
const redirectPath = route.query.redirect || '/dashboard'
router.push(redirectPath)
}
}
</script>
(3)路由独享守卫(单个路由拦截)
在特定路由规则中配置 beforeEnter,仅拦截当前路由:
const routes = [
{
path: '/dashboard',
component: Dashboard,
// 路由独享守卫:仅访问该路由时触发
beforeEnter: (to, from) => {
const token = localStorage.getItem('token')
if (!token) {
return '/login' // 未登录 → 重定向到登录页
}
}
}
]
(4)组件内守卫(组件级拦截)
在组件内通过 onBeforeRouteEnter 拦截路由进入,适合组件专属逻辑:
<!-- Dashboard.vue -->
<script setup>
import { onBeforeRouteEnter } from 'vue-router'
import { ElMessage } from 'element-plus' // 示例:UI 组件提示
// 组件内守卫:进入该组件前触发
onBeforeRouteEnter((to, from) => {
const role = localStorage.getItem('role') // 获取用户角色
// 逻辑:仅管理员可访问,普通用户重定向到首页
if (role !== 'admin') {
ElMessage.warning('无权限访问,已跳转首页')
return '/' // 重定向到首页
}
})
</script>
三、特殊场景重定向
1. 404 页面重定向(路由未匹配时)
配置通配符路由,当访问不存在的路径时,重定向到 404 页面或首页:
const routes = [
// 其他路由...
{ path: '/404', component: () => import('@/views/404.vue') },
// 通配符路由(必须放在最后):匹配所有未定义的路由
{ path: '/:pathMatch(.*)*', redirect: '/404' }
// 或直接重定向到首页:{ path: '/:pathMatch(.*)*', redirect: '/' }
]
2. 带参数的重定向
无论是路由配置还是编程式导航,都支持携带 params 或 query 参数:
// 1. 路由配置中带参数
{ path: '/old-user', redirect: { name: 'User', params: { id: 1 }, query: { type: 'old' } } }
// 2. 编程式导航带参数
router.push({
name: 'User',
params: { id: 1 }, // 路径参数(需路由配置占位符:/user/:id)
query: { type: 'old' } // 查询参数(拼接在路径后:?type=old)
})
四、注意事项
-
History 模式需后端配置 :若使用
createWebHistory(History 模式),后端需配置所有路由指向index.html(避免刷新 404),Nginx 示例配置:location / { try_files $uri $uri/ /index.html; }若无需后端配置,可改用
createWebHashHistory(Hash 模式,路径含#)。 -
避免无限重定向 :重定向目标路由不能再次指向自身(如
/a重定向到/b,/b又重定向到/a),会导致浏览器崩溃,需通过白名单、条件判断规避。 -
Vue Router 4 语法变化:
- 不再支持
this.$router在setup中使用,需通过useRouter钩子获取。 - 路由守卫中无需
next(),直接return 路由对象或return true放行。
- 不再支持
五、汇总不同场景选择建议
| 场景 | 推荐重定向方式 |
|---|---|
| 初始化路由自动跳转(如根路径) | 路由配置式重定向(redirect) |
| 组件内交互触发(如按钮点击) | 编程式导航(router.push/replace) |
| 全局权限控制(如未登录拦截) | 全局守卫(router.beforeEach) |
| 单个路由拦截(如管理员路由) | 路由独享守卫(beforeEnter) |
| 旧路径兼容、404 页面 | 路由配置式重定向(通配符 / 固定路径) |