当前位置: 首页 > news >正文

Vue Router完全指南 —— 从基础配置到权限控制

前面两篇我分为讲了vue的一些基本和常用的语法,现在这篇文章带你了解vue的路由管理是怎么实现的

引言

在 Vue 开发单页应用(SPA)时,“页面跳转不刷新、URL 与组件联动” 是核心需求 —— 而 Vue Router 就是实现这一需求的官方工具。它通过管理 “路径(path)与组件(component)” 的对应关系,让我们能像浏览多页网站一样切换内容,却始终保持单页应用的流畅性。本文将从基础配置入手,一步步解锁路由导航、传参、嵌套、守卫等进阶能力,帮你搞定任何 Vue 项目的路由管理。

一、先搞懂:Vue Router 核心概念

在写代码前,我们得先理清几个关键概念,避免后续混淆。

1.1 什么是路由?

路由本质是一组 key-value 的对应关系。在前端路由中:

  • key:URL 路径(如/home
  • value:对应渲染的组件(如Home.vue

多个路由需要通过 “路由器” 统一管理,Vue Router 就是这个 “路由器”,负责监听 URL 变化,渲染对应的组件。

1.2 SPA 应用的特点

Vue Router 服务于 SPA(单页 Web 应用),这类应用有 4 个核心特点:

  1. 整个应用只有 1 个完整 HTML 页面(index.html);
  2. 点击导航不刷新页面,只做局部内容更新
  3. URL 变化通过前端路由控制,而非后端跳转;
  4. 数据需通过 Ajax/axios 异步获取。

1.3 路由项目目录结构

一个标准的 Vue+Vue Router 项目结构如下(重点关注router目录):

src/
├── router/          # 路由配置目录
│   └── index.ts     # 路由规则与路由器创建
├── views/           # 路由页面组件(如Home.vue、About.vue)
├── components/      # 通用功能组件
├── App.vue          # 根组件(放导航与路由出口)
└── main.ts          # 入口文件(注册路由器)

二、入门:Vue Router 4 基础使用

从安装到实现第一个路由跳转,只需 4 步,全程可复制使用。

2.1 步骤 1:安装 Vue Router 4

Vue 3 对应的路由版本是 Vue Router 4,通过 npm 安装:

npm install vue-router@4

2.2 步骤 2:创建路由器

src/router/index.ts中,用createRouter创建路由器,定义路由规则(routes):

// src/router/index.ts
import { createRouter, createWebHistory } from "vue-router";
// 导入路由页面组件
import Home from "@/views/Home.vue";
import News from "@/views/News.vue";
import About from "@/views/About.vue";// 1. 定义路由规则:path -> component的对应关系
const routes = [{path: "/home",    // URL路径name: "home",     // 命名路由(可选,用于简化跳转)component: Home   // 对应组件},{path: "/news",name: "news",component: News},{path: "/about",name: "about",component: About}
];// 2. 创建路由器
const router = createRouter({history: createWebHistory(), // 路由模式(history模式,无#)routes                       // 传入路由规则
});// 3. 导出路由器,供main.ts注册
export default router;

2.3 步骤 3:注册路由器

在入口文件src/main.ts中,通过app.use(router)注册路由器,让整个应用支持路由

// src/main.ts
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router"; // 导入路由器const app = createApp(App);
app.use(router); // 注册路由器
app.mount("#app");

2.4 步骤 4:使用路由(导航 + 展示)

在根组件App.vue中,用两个核心组件实现路由功能:

  • RouterLink:替代<a>标签的导航组件,点击不刷新页面;
  • RouterView:路由组件的 “容器”,URL 匹配的组件会渲染在这里。

代码示例:

<template><div class="app"><h1>Vue Router 测试</h1><!-- 1. 导航区:用RouterLink实现跳转 --><div class="nav"><!-- active-class:跳转后添加的激活样式 --><RouterLink to="/home" active-class="active">首页</RouterLink><RouterLink to="/news" active-class="active">新闻</RouterLink><RouterLink to="/about" active-class="active">关于</RouterLink></div><!-- 2. 展示区:RouterView渲染匹配的组件 --><div class="content"><RouterView></RouterView></div></div>
</template><script setup lang="ts" name="App">
// 导入RouterLink和RouterView(setup语法糖需手动导入)
import { RouterLink, RouterView } from "vue-router";
</script><style scoped>
.nav { margin: 20px 0; }
.nav a { margin-right: 20px; text-decoration: none; }
.active { color: #42b983; font-weight: bold; } /* 激活样式 */
</style>

三、核心配置:路由模式与跳转方式

这部分解决两个常见问题:“URL 带不带 #?”“怎么简化跳转写法?”

3.1 路由模式:history vs hash

Vue Router 提供两种 URL 模式,核心区别是 URL 是否带#,需在创建路由器时配置:

模式配置代码优点缺点
history 模式history: createWebHistory()URL 无 #,美观,接近传统网站上线需服务端配置(否则刷新 404)
hash 模式history: createWebHashHistory()兼容性好,无需服务端处理URL 带 #,SEO 优化较差

注意:history 模式需服务端配置(如 Nginx 转发所有请求到index.html),否则用户刷新非首页会报 404;hash 模式无需额外配置,适合快速原型或兼容性要求高的场景。

3.2 路由跳转:to 的两种写法

RouterLinkto属性支持两种写法,可根据场景选择:

写法 1:字符串写法(简单场景)

直接写完整路径,适合无参数的跳转:

<!-- 字符串写法:直接指定路径 -->
<RouterLink to="/home">首页</RouterLink>
<!-- 带query参数的字符串写法(后面讲传参时详细说) -->
<RouterLink to="/news/detail?id=1&title=新闻标题">新闻详情</RouterLink>
写法 2:对象写法(复杂场景)

当需要传参数或用 “命名路由” 简化路径时,用对象写法更灵活:

<!-- 1. 仅指定路径 -->
<RouterLink :to="{ path: '/home' }">首页</RouterLink><!-- 2. 用命名路由(需先给路由配置name) -->
<RouterLink :to="{ name: 'home' }">首页</RouterLink> 
<!-- 优势:无需写完整路径,路径变了也不用改这里 --><!-- 3. 带参数(后面传参章节详解) -->
<RouterLink :to="{ name: 'newsDetail', params: { id: 1, title: '新闻标题' } 
}">新闻详情</RouterLink>

3.3 命名路由:简化跳转的 “快捷键”

给路由规则配置name属性(命名路由),可替代完整路径,减少路径修改时的工作量。

步骤 1:给路由配置 name
// src/router/index.ts
const routes = [{name: "home",     // 命名路由:name唯一,建议语义化path: "/home",component: Home},{name: "newsDetail", // 新闻详情的命名路由path: "/news/detail/:id/:title", // 带params占位(后面讲)component: NewsDetail}
];
步骤 2:用 name 跳转
<!-- 无需写完整路径,用name即可 -->
<RouterLink :to="{ name: 'newsDetail', params: { id: 1, title: '标题' } }">新闻详情
</RouterLink>

优势:若后续/news/detail路径改成/news/content,只需修改路由配置的path,所有用name跳转的代码无需改动,降低维护成本。

四、进阶:嵌套路由与路由传参

这部分解决 “页面内嵌套子组件”(如新闻列表→新闻详情)和 “页面间传递数据”(如列表→详情传 ID)的核心需求。

4.1 嵌套路由:实现 “父组件 - 子组件” 联动

场景:新闻页面(News.vue)中,左侧是新闻列表,右侧是新闻详情,点击列表项切换详情 —— 这就需要嵌套路由(父路由/news,子路由/news/detail)。

步骤 1:配置嵌套路由(children)

在父路由(如/news)中用children配置子路由,子路由的path无需加/(会自动拼接父路由路径):

// src/router/index.ts
const routes = [{name: "news",path: "/news",component: News, // 父组件:新闻列表页// 子路由配置:children是数组,每个元素是子路由规则children: [{name: "newsDetail",path: "detail/:id/:title", // 子路由path:无需加/,拼接后是/news/detailcomponent: NewsDetail // 子组件:新闻详情页}]}
];
步骤 2:父组件中预留 “子路由出口”

父组件(News.vue)中需添加RouterView,子组件会渲染在这里:

<!-- News.vue(父组件) -->
<template><div class="news-page"><!-- 左侧:新闻列表(父组件内容) --><div class="news-list"><RouterLink v-for="item in newsList" :key="item.id":to="{ name: 'newsDetail', params: { id: item.id, title: item.title } }">{{ item.title }}</RouterLink></div><!-- 右侧:子路由出口(子组件NewsDetail会渲染在这里) --><div class="news-detail"><RouterView></RouterView></div></div>
</template><script setup lang="ts" name="News">
import { ref } from "vue";
import { RouterLink, RouterView } from "vue-router";// 模拟新闻列表数据
const newsList = ref([{ id: 1, title: "Vue Router 4 新特性" },{ id: 2, title: "SPA应用路由最佳实践" }
]);
</script>

4.2 路由传参:query vs params 两种方式

页面间传递数据(如列表→详情传 ID)是路由核心需求,Vue Router 提供两种传参方式,适用场景不同。

方式 1:query 参数(URL 可见,可选参数)

query 参数会拼在 URL 后面(如/news/detail?id=1&title=标题),类似 GET 请求参数,适合传递 “可选参数”(如筛选条件、分页)。

步骤 1:传递 query 参数
<!-- 写法1:字符串写法(简单) -->
<RouterLink to="/news/detail?id=1&title=Vue Router 教程">新闻详情</RouterLink><!-- 写法2:对象写法(推荐,参数清晰) -->
<RouterLink :to="{ path: '/news/detail', // 或用name: 'newsDetail'query: { id: 1, title: 'Vue Router 教程' } 
}">新闻详情</RouterLink>
步骤 2:接收 query 参数

在子组件(NewsDetail.vue)中,用useRoute钩子获取路由信息,从route.query中取参数:

<!-- NewsDetail.vue -->
<script setup lang="ts" name="NewsDetail">
import { useRoute } from "vue-router";// 1. 获取路由实例(包含参数、路径等信息)
const route = useRoute();// 2. 接收query参数(注意:参数类型都是字符串)
const newsId = route.query.id; // "1"
const newsTitle = route.query.title; // "Vue Router 教程"console.log("新闻ID:", newsId);
</script>
方式 2:params 参数(URL 占位,必需参数)

params 参数通过 “路径占位” 传递(如/news/detail/1/标题),URL 中不显示参数名,适合传递 “必需参数”(如资源 ID,符合 RESTful 风格)。

步骤 1:路由规则中 “占位”

先在子路由的path中用:参数名占位,声明需要接收的 params 参数:

// src/router/index.ts
const routes = [{name: "news",path: "/news",component: News,children: [{name: "newsDetail",// 占位::id和:title对应params的两个参数path: "detail/:id/:title", component: NewsDetail}]}
];
步骤 2:传递 params 参数
<!-- 写法1:字符串写法(需按占位顺序传) -->
<RouterLink :to="`/news/detail/${item.id}/${item.title}`">{{ item.title }}
</RouterLink><!-- 写法2:对象写法(必需用name,不能用path!) -->
<RouterLink :to="{ name: 'newsDetail', // 注意:params传参不能用pathparams: { id: item.id, title: item.title } 
}">{{ item.title }}
</RouterLink>
步骤 3:接收 params 参数

与 query 类似,从route.params中取参数:

<script setup lang="ts" name="NewsDetail">
import { useRoute } from "vue-router";const route = useRoute();// 接收params参数(类型也是字符串)
const newsId = route.params.id; // "1"
const newsTitle = route.params.title; // "Vue Router 教程"
</script>
query vs params 核心对比
对比维度query 参数params 参数
URL 显示?id=1&title=标题/1/标题(路径占位)
路由配置无需额外配置需在 path 中占位(:id/:title
跳转方式支持 path/name仅支持 name(对象写法)
参数必要性可选(可不传)必需(不传会导致路径错误)
适用场景筛选条件、分页、可选参数资源 ID、必需参数(RESTful)

五、优化:路由 props 与编程式导航

这部分解决 “组件解耦” 和 “非点击触发跳转”(如登录成功后跳转)的需求。

5.1 路由 props:让组件 “少依赖路由实例”

默认情况下,组件需通过route.query/route.params取参数,导致组件与路由强耦合(脱离路由就用不了)。用props配置可将路由参数 “注入” 为组件的 props,让组件更通用。

Vue Router 的props支持三种写法,覆盖不同场景:

写法 1:布尔值写法(仅 params 参数)

props: true时,路由的 params 参数会自动转为组件的 props:

// 1. 路由配置:props: true
const routes = [{name: "newsDetail",path: "detail/:id/:title",component: NewsDetail,props: true // 开启props,params参数转为组件props}
];// 2. 组件接收:用defineProps
<script setup lang="ts" name="NewsDetail">
// 直接接收props,无需依赖useRoute
defineProps(["id", "title"]);// 使用时直接用id/title,不用route.params
console.log("新闻ID:", id); // 无需.route.params.id
</script>
写法 2:对象写法(固定参数)

传递固定的静态参数,适合参数不依赖路由的场景:

// 路由配置:props是对象
const routes = [{path: "/user",component: User,props: { role: "guest", status: "active" } // 固定参数}
];// 组件接收
<script setup lang="ts" name="User">
defineProps(["role", "status"]);
console.log(role); // "guest"
</script>
写法 3:函数写法(灵活处理参数)

支持自定义参数逻辑,可整合 query/params 参数,或对参数加工:

// 路由配置:props是函数,接收route参数
const routes = [{path: "/news/detail",component: NewsDetail,// 函数返回的对象会作为props传给组件props: (route) => ({id: route.query.id, // 取query参数title: route.query.title,time: new Date().toLocaleString() // 额外加动态参数})}
];// 组件接收
<script setup lang="ts" name="NewsDetail">
defineProps(["id", "title", "time"]);
console.log(time); // 当前时间
</script>

优势:组件无需导入useRoute,脱离路由环境也能通过 props 传参使用(如单元测试、组件复用)。

5.2 编程式导航:非点击触发跳转

除了RouterLink(声明式导航),还可通过代码触发跳转(如登录成功后、接口请求成功后),这就是编程式导航,核心是useRouter钩子。

步骤 1:导入 useRouter 与 useRoute
<script setup lang="ts">
import { useRouter, useRoute } from "vue-router";const router = useRouter(); // 用于跳转(控制路由)
const route = useRoute();   // 用于获取当前路由信息(参数、路径等)
</script>
步骤 2:常用编程式导航方法
// 1. 跳转到指定路径(字符串写法)
router.push("/home");// 2. 跳转到指定路径(对象写法,带query参数)
router.push({path: "/news/detail",query: { id: 1, title: "标题" }
});// 3. 用命名路由跳转(带params参数)
router.push({name: "newsDetail",params: { id: 1, title: "标题" }
});// 4. 替换当前历史记录(不会新增历史条目,后退不会回到当前页)
// 场景:登录页→首页,后退不想回到登录页
router.replace("/home");// 5. 后退/前进(类似浏览器的前进后退按钮)
router.go(-1); // 后退1步
router.go(1);  // 前进1步
router.back(); // 等价于go(-1)
router.forward(); // 等价于go(1)

六、异常处理:重定向与 404 页面

处理 “默认首页” 和 “无效路径” 的场景,提升用户体验。

6.1 重定向:默认路径跳转

当用户访问根路径(/)时,自动跳转到首页(/home),用redirect配置:

// src/router/index.ts
const routes = [// 重定向:访问/时,自动跳转到/home{ path: "/", redirect: "/home" },// 其他路由规则{ path: "/home", component: Home },{ path: "/about", component: About }
];

也支持重定向到命名路由:

{ path: "/", redirect: { name: "home" } }

6.2 404 页面:无效路径处理

当用户访问不存在的路径时,显示 404 页面,需用 “通配符” 匹配所有未定义的路径。

步骤 1:创建 404 组件(NotFound.vue)
<!-- src/views/NotFound.vue -->
<template><div class="not-found"><h1>404</h1><p>页面不存在</p><RouterLink to="/home">返回首页</RouterLink></div>
</template>
步骤 2:配置通配符路由

通配符/:pathMatch(.*)*会匹配所有未定义的路径,需放在路由规则的最后面(路由匹配按顺序执行):

// src/router/index.ts
import NotFound from "@/views/NotFound.vue";const routes = [// 其他路由规则...// 404页面:放在最后面{path: "/:pathMatch(.*)*", // 通配符,匹配所有未定义路径name: "NotFound",component: NotFound}
];

七、权限控制:路由守卫的核心应用

路由守卫是 Vue Router 的 “安全门”,可在路由跳转前 / 后执行逻辑(如登录验证、角色权限判断),核心是控制 “谁能访问哪个页面”。

7.1 路由守卫的分类与执行顺序

Vue Router 提供 3 类守卫,执行顺序如下(从跳转开始到结束):

  1. 全局前置守卫(beforeEach):所有路由跳转前执行(最常用,如登录验证);
  2. 路由独享守卫(beforeEnter):仅当前路由跳转前执行(单独配置某路由);
  3. 组件内守卫(beforeRouteEnter):进入组件前执行(组件内配置);
  4. 全局解析守卫(beforeResolve):所有路由跳转前,组件内守卫执行后;
  5. 全局后置钩子(afterEach):所有路由跳转后执行(无导航控制能力,如修改页面标题)。

7.2 最常用:全局前置守卫(beforeEach)

全局前置守卫是权限控制的核心,在src/router/index.ts中配置,每次路由跳转前都会触发,可控制 “是否允许跳转”。

实战:登录验证(未登录跳登录页)
// src/router/index.ts
import { createRouter, createWebHistory } from "vue-router";
import Home from "@/views/Home.vue";
import Login from "@/views/Login.vue";const routes = [{ path: "/", redirect: "/home" },{ path: "/home", component: Home },{ path: "/about", component: () => import("@/views/About.vue") }, // 懒加载{ path: "/login", name: "Login", component: Login },// 需要登录才能访问的页面:添加meta.requiresAuth标记{path: "/user/center",component: () => import("@/views/UserCenter.vue"),meta: { requiresAuth: true } // 标记:需登录才能访问},{ path: "/:pathMatch(.*)*", component: () => import("@/views/NotFound.vue") }
];const router = createRouter({history: createWebHistory(),routes
});// 全局前置守卫:登录验证
router.beforeEach(async (to, from, next) => {// to:即将进入的目标路由(要去哪里)// from:当前离开的路由(从哪里来)// next:控制导航的函数(允许/禁止/重定向)// 1. 检查目标路由是否需要登录const needLogin = to.meta.requiresAuth;if (needLogin) {// 2. 检查本地是否有登录令牌(token)const token = localStorage.getItem("token");if (!token) {// 3. 未登录:重定向到登录页,并携带“当前路径”(登录后返回)next({name: "Login",query: { redirect: to.fullPath } // redirect:记录要访问的页面});return;}// 4. 已登录:验证token有效性(模拟接口)const isTokenValid = await mockValidateToken(token);if (!isTokenValid) {// token无效:清除token,重定向到登录页localStorage.removeItem("token");next({ name: "Login", query: { redirect: to.fullPath } });return;}}// 5. 无需登录或已登录:允许跳转next();
});// 模拟token验证接口
const mockValidateToken = (token: string) => {return new Promise((resolve) => {// 实际项目中调用后端接口验证tokensetTimeout(() => {resolve(token === "valid-token"); // 假设valid-token是有效token}, 300);});
};export default router;

总结

Vue Router 是 Vue SPA 应用的 “骨架”,掌握它的核心配置(嵌套、传参、守卫),就能应对从简单博客到复杂管理系统的路由需求。建议从 “个人博客路由系统” 开始实践,逐步加入权限控制和面包屑导航,巩固所学知识点。

http://www.dtcms.com/a/503787.html

相关文章:

  • 给别人做的网站涉及到违法修改WordPress的配置文件
  • 程序员与编译器
  • 含山县查询建设工程的网站v9做的网站被攻击链接吧跳转
  • 建盏公司官方网站厦门外贸商城网站建设
  • 多模态RAG进阶:基于GPT-4V+LangGraph的下一代智能体系统完全指南
  • 自己在电脑上建文档做网站怎么做宝塔面板 wordpress制作网页
  • Docker核心揭秘:轻量级虚拟化的革命
  • 网站首页新世纪建设集团有限公司安阳贴吧论坛
  • 网站不备案可以做百度竞价吗做网站过程视频
  • 计算机网络5
  • 【论文笔记】李飞飞 世界模型RTFM
  • 微信小程序开发哪个好优化关键词排名工具
  • Text2SQL与工作流实现:让数据库查询变得轻松又高效
  • 【Android】浅析 Android 的 IPC 跨进程通信机制
  • C#11--14新特性
  • 力扣热题100道之最大子数之和
  • 手机网站开发c 教程一嗨租车网站建设的功能特色
  • 购物网站 app网站建设时应该做的优化
  • 深圳网站建设raygf2022年免费ppt模板下载
  • 【Python】二.判断语句
  • 【数据集】最新全国景区A-5A级景区数据集(更新至2025年)-含矢量及Excel详细
  • Linux线程 --- 线程控制、pthread线程库、线程栈、线程本地存储
  • C++:从0开始学习链表(练习)
  • JAVA的Set集合类
  • linux系统中进程控制
  • 网站域名注册证书是什么视频拍摄设备
  • 下载 LibreCAD 并创建个人分支的 Git 操作指南
  • 石家庄大型网站建站网站开发能从事那些职业
  • JavaScript性能优化实战大纲性能优化的核心目标
  • 【Android】布局优化:include、merge、ViewStub的使用及注意事项