编程式导航是 Vue Router 4 专为 Vue 3 提供的代码级路由控制方案,通过调用路由实例 API 实现应用内的路由切换,完全脱离 HTML 链接的依赖。开发者可在表单提交、权限校验、异步请求等业务逻辑中,动态控制跳转时机、传递路由参数、操作浏览器历史记录,实现路径与组件数据的联动更新,是构建复杂交互单页应用(SPA)的核心能力。
编程式导航指通过 JavaScript 代码 主动控制路由跳转,替代 <router-link> 声明式导航。在 Vue 3 组合式 API 中,必须通过 useRouter() 函数获取路由实例,这是执行所有编程式导航的唯一入口。该方案支持动态传参、条件跳转、历史记录管理,与业务逻辑深度绑定,适配登录验证、表单提交、权限拦截等复杂场景。
Vue Router 4 提供 3 类标准化导航方法,对应不同的浏览器历史记录操作规则。
router.push() 是最常用的导航方法,向历史栈添加新记录,点击浏览器后退可返回上一页面。
声明式等价写法:<router-link :to="...">
编程式核心 API:router.push(...)
支持字符串路径、路由对象两种传参方式,Vue Router 4 强制规则:path 与 params 不可混用,参数会失效。
import { useRouter } from 'vue-router';
const router = useRouter();
// 1. 字符串路径(最简写法)
router.push('/home/dashboard');
// 2. 路径对象
router.push({ path: '/home/products' });
// 3. 命名路由 + params(推荐,适配动态路由)
router.push({ name: 'Product', params: { id: '123' } });
// 4. 带查询参数(? 拼接)
router.push({ path: '/product', query: { id: '123' } });
// 5. 带锚点(hash)
router.push({ path: '/about', hash: '#team' });router.replace() 作用与 push 一致,不会新增历史记录,直接替换当前栈条目,后退无法返回当前页。
适用于登录页、支付页等禁止用户返回的场景。
声明式等价写法:<router-link :to="..." replace>
编程式核心 API:router.replace(...)
// 标准写法
router.replace({ path: '/home/dashboard' });
// 简化写法(等价于 replace)
router.push({ path: '/home', replace: true });router.go() 接收整数参数,控制历史记录前进 / 后退,等价于 window.history.go(n);
同时提供快捷方法 back()、forward()。
// 后退 1 页(等价于浏览器返回按钮)
router.go(-1);
router.back();
// 前进 1 页
router.go(1);
router.forward();
// 前进 3 页
router.go(3);
// 无对应记录时,静默失效
router.go(-100);结合前文动态路由、嵌套路由,提供企业级参数传递规范:
动态路径参数:必须使用 命名路由 + params
查询参数:可搭配 path/name 自由使用
嵌套路由跳转:推荐使用命名路由,避免硬编码长路径
基于 Element Plus 实现登录表单校验,结合编程式导航完成登录验证,衔接前文嵌套路由配置,登录成功后跳转到后台仪表盘,登录失败给出友好提示。创建 src/views/Login.vue
<template>
<div class="login-container">
<el-card class="login-card">
<h1 class="text-center text-2xl font-bold mb-8">欢迎登录</h1>
<el-form :model="form" :rules="rules" ref="formRef">
<el-form-item label="账号:" prop="username">
<el-input v-model="form.username" placeholder="请输入账号" clearable />
</el-form-item>
<el-form-item label="密码:" prop="password">
<el-input v-model="form.password" type="password" placeholder="请输入密码" show-password />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm" block>登录</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</template>
<script setup lang="ts">
import { reactive, ref } from 'vue';
import { ElMessage } from 'element-plus';
import type { FormInstance, FormRules } from 'element-plus';
// 导入路由核心 API
import { useRouter } from 'vue-router';
// 获取路由实例
const router = useRouter();
// 表单实例
const formRef = ref<FormInstance>();
// 登录表单数据
const form = reactive({
username: '',
password: ''
});
// 表单校验规则
const rules = reactive<FormRules>({
username: [{ required: true, message: '请输入账号', trigger: 'blur' }],
password: [{ required: true, message: '请输入密码', trigger: 'blur' }]
});
// 登录提交逻辑
const submitForm = async () => {
const formEl = formRef.value;
if (!formEl) return;
// 执行表单校验
await formEl.validate((valid) => {
if (valid) {
// 模拟账号密码校验
if (form.username === 'admin' && form.password === '123456') {
ElMessage.success('登录成功');
// 编程式导航:跳转到仪表盘(替换历史记录,禁止返回登录页)
router.replace({ name: 'Dashboard' });
} else {
ElMessage.error('账号或密码错误');
}
}
});
};
</script>
<style scoped>
.login-container {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #f5f7fa;
}
.login-card {
width: 360px;
padding: 40px;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
</style>追加路由 src\router\index.ts
// 登录路由
{
path: '/login',
name: 'Login',
component: () => import('../views/Login.vue')
},Vue Router 4 导航方法返回 Promise,支持异步监听跳转结果:
// 异步等待导航完成
router.push({ name: 'Dashboard' }).then(() => {
console.log('跳转成功');
}).catch((err) => {
console.log('跳转失败', err);
});企业开发中禁止硬编码路径,统一使用命名路由,便于后期维护:
// 推荐(无硬编码)
router.push({ name: 'Dashboard' });
// 不推荐
router.push('/home/dashboard');