- 前端
- 路由
【免费下载链接】vue-router
🚦 The official router for Vue 2
<router-link>是 vue-router(Vue 2 官方路由)中用于在启用路由的应用里触发用户导航的核心声明式组件:它以toprop 指定目标位置,默认渲染为带正确href的<a>标签,并能在目标路由激活时自动为链接添加 active CSS 类。阅读本文后,你将掌握<router-link>全部 props 的用法与默认值、active 类“包含匹配”与“精确匹配”的差异,以及其在 src/components/link.js 中的底层实现原理(如router.resolve、isIncludedRoute、guardEvent)。
<router-link>是什么
在基于 vue-router 的应用中,页面间跳转最常见的写法不是手写<a href="...">,而是使用<router-link>组件。它负责三件核心事情:
- 根据
toprop 解析出真实的目标地址,并渲染为带有正确href的<a>标签; - 拦截点击事件并交给路由内部处理,避免浏览器整页刷新;
- 在目标路由处于激活状态时,自动为链接应用 active CSS 类,方便开发者做导航高亮。
默认情况下它渲染为<a>标签,但可以通过tagprop 改造成任意标签,同时仍然监听点击事件完成导航。
为什么用<router-link>而不是硬编码<a href="...">
原文档(docs-gitbook/kr/api/router-link.md)给出了三条理由,这也是该项目官方推荐使用<router-link>的根本原因:
- 跨模式行为一致:无论路由器工作在 HTML5 History 模式还是 Hash 模式,
<router-link>都以相同方式工作。当你决定切换模式,或路由器因 IE9 等环境自动回退到 Hash 模式时,模板代码完全无需改动。 - 阻止浏览器整页刷新:在 HTML5 History 模式下,
<router-link>会拦截点击事件,避免浏览器执行默认行为导致页面重新加载。这一点在源码guardEvent中有完整的实现(见下文“点击拦截的实现”一节),它通过e.preventDefault()阻断默认跳转,再把导航交给路由内部的push/replace流程。 - 自动处理
base路径:在 HTML5 History 模式下配置了base选项时,toprop 中不需要重复包含 base 前缀,路由会替你处理。
Props 完整说明
以下 props 均继承自原文档,并补充了本仓库 types/router.d.ts 与 src/components/link.js 中的类型约束与实现细节。
to
- 类型:
string | Location - 必填
表示链接的目标路由。点击时,to的值会被内部传给router.push(),因此它既可以是字符串,也可以是位置描述符(Location)对象:
<!-- 字面量字符串 --> <router-link to="home">Home</router-link> <!-- 渲染结果 --> <a href="home">Home</a> <!-- 使用 v-bind 绑定表达式 --> <router-link v-bind:to="'home'">Home</router-link> <!-- 省略 v-bind,与绑定其他 prop 写法一致 --> <router-link :to="'home'">Home</router-link> <!-- 与上面等价的对象写法 --> <router-link :to="{ path: 'home' }">Home</router-link> <!-- 具名路由 --> <router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link> <!-- 带查询参数,将解析为 /register?plan=private --> <router-link :to="{ path: 'register', query: { plan: 'private' }}">Register</router-link>从源码看,to的类型校验为[String, Object](见 src/components/link.js),对象形式的{ path }、{ name, params }、{ path, query }都是合法的 Location 描述符。
replace
- 类型:
boolean - 默认值:
false
设置replace后,点击时调用的是router.replace()而不是router.push(),因此导航不会产生新的历史记录,浏览器的“后退”按钮无法回到该页面:
<router-link :to="{ path: '/abc'}" replace></router-link>源码中对应的分支在 src/components/link.js:handler内根据this.replace决定调用router.replace(location, noop)还是router.push(location, noop)。
append
- 类型:
boolean - 默认值:
false
设置append后,相对路径会被始终追加到当前路径之后。例如当前在/a,点击相对链接b:不加append会到达/b,加了append则到达/a/b:
<router-link :to="{ path: 'relative/path'}" append></router-link>实现上,append会作为第三个参数传给router.resolve(this.to, current, this.append)(见 src/components/link.js),由路由解析逻辑决定相对路径的拼接方式。
tag
- 类型:
string - 默认值:
"a"
有时我们希望<router-link>渲染成<li>等其他标签,此时用tag指定要渲染的标签,组件仍会持续监听点击事件来完成导航:
<router-link to="/foo" tag="li">foo</router-link> <!-- 渲染结果 --> <li>foo</li>从源码看,当tag不是"a"时,组件会在插槽内递归查找第一个<a>子元素,把href和事件监听挂到该<a>上;如果找不到<a>子元素,则把监听器挂到tag指定的元素自身上(见 src/components/link.js)。
注意:本仓库(版本 3.6.5,见 package.json)会在开发环境对
tag与eventprops 给出弃用警告,提示它们在 Vue Router 4 中已被移除,建议改用 v-slot API。
active-class
- 类型:
string - 默认值:
"router-link-active"
配置链接处于激活状态时应用的 CSS 类名。默认值也可以通过路由构造选项linkActiveClass进行全局配置。
exact
- 类型:
boolean - 默认值:
false
默认的激活类匹配行为是包含匹配(inclusive match)。例如<router-link to="/a">只要当前路径以/a或/a/开头,就会应用激活类。
由此带来的一个后果是:<router-link to="/">会对所有路由都保持激活状态!如果要强制链接进入“精确匹配模式”,请使用exact:
<!-- 此链接仅在路径为 / 时激活 --> <router-link to="/" exact>包含匹配与精确匹配的判定分别由 src/util/route.js 中的isIncludedRoute与isSameRoute实现(详见下文“激活类的判定原理”)。
event
- 版本要求:2.1.0+
- 类型:
string | Array<string> - 默认值:
'click'
指定哪些事件可以触发链接导航,可以是单个事件名,也可以是事件名数组。源码中的类型校验为[String, Array](见 src/components/link.js),事件绑定逻辑见 src/components/link.js:如果是数组则逐个on[e] = handler,否则on[this.event] = handler。
exact-active-class
- 版本要求:2.5.0+
- 类型:
string - 默认值:
"router-link-exact-active"
指定链接在“精确匹配”状态下应用 CSS 类。默认值可以通过路由构造选项linkExactActiveClass全局配置。
本仓库新增的扩展 props
除原文档列出的 props 外,本仓库版本还提供了以下扩展(定义于 src/components/link.js 与 types/router.d.ts):
- exact-path:
boolean,默认false。仅用 URL 的path部分做精确匹配,忽略query和hash。例如<router-link to="/search" exact-path>在/search?page=2或/search#filters下同样激活。对应类型声明见 types/router.d.ts。 - exact-path-active-class:
string,默认"router-link-exact-path-active",可通过路由构造选项linkExactPathActiveClass全局配置。 - aria-current-value:
'page' | 'step' | 'location' | 'date' | 'time' | 'true' | 'false',默认"page"。在链接精确激活时设置到aria-current属性上,默认值page通常是最佳选择,类型定义见 types/router.d.ts。 - custom:
boolean,默认false。配合 v-slot API 使用,取消 Vue Router 4 中默认包裹<a>的迁移警告。
v-slot 作用域插槽 API
源码 src/components/link.js 还实现了作用域插槽:默认插槽会收到{ href, route, navigate, isActive, isExactActive }对象,允许完全自定义渲染内容:
<router-link :to="{ name: 'user', params: { userId: 123 }}" custom v-slot="{ href, route, navigate, isActive }"> <a :href="href" @click="navigate" :class="{ active: isActive }">{{ route.params.userId }}</a> </router-link>将 active 类应用到外部元素
有时我们希望激活类出现在<a>自身之外的容器元素上。做法是:让<router-link>渲染外层元素,并在内部手写原生<a>:
<router-link tag="li" to="/foo"> <a>/foo</a> </router-link>此时<a>才是真正的链接(会获得正确的href),而激活类会应用在外层的<li>上。这个行为与源码中“tag非a时查找内部首个<a>元素并挂接 href 与事件”的逻辑完全一致(src/components/link.js)。仓库自带的 examples/active-links/app.js 中也包含同款示例:<router-link tag="li" to="/about"><a>/about (active class on outer element)</a></router-link>。
源码深挖:激活类的判定原理
激活类的计算集中在 src/components/link.js,核心逻辑如下:
- 通过
router.resolve(this.to, current, this.append)得到location、route和href(src/components/link.js); - 读取全局配置
router.options.linkActiveClass与linkExactActiveClass,若未配置则回退到"router-link-active"/"router-link-exact-active";组件自身的activeClass/exactActiveClassprop 优先级最高(src/components/link.js); - 处理重定向:若目标路由存在
redirectedFrom,会先基于它构造对比目标,保证重定向前的链接也能正确高亮(src/components/link.js); - 精确激活类
exactActiveClass由isSameRoute(current, compareTarget, this.exactPath)决定;非精确的包含类activeClass在exact或exactPath开启时直接取精确匹配结果,否则由isIncludedRoute(current, compareTarget)决定(src/components/link.js)。
两个判定函数定义在 src/util/route.js:
isSameRoute:比较 path(忽略结尾斜杠差异)、hash 与 query(含嵌套对象比较),onlyPath为真时只比较 path;isIncludedRoute:判断当前路径是否以目标路径为前缀(同样先规范化结尾斜杠),同时要求 hash 与 query 满足包含关系——这正是文档所说的“包含匹配”。
点击拦截的实现:guardEvent
当tag为"a"或使用默认事件时,点击处理由guardEvent完成(src/components/link.js)。它会主动放行以下场景,其余情况一律preventDefault()并返回true交给路由导航:
- 按住修饰键(
metaKey、altKey、ctrlKey、shiftKey)时不拦截——保留浏览器在新标签页打开链接的能力; - 事件已被
preventDefault()调用过时不重复处理; - 非左键点击(如右键)不处理;
target="_blank"的链接不拦截。
拦截成功后,handler 根据replace调用router.replace或router.push(src/components/link.js),从而完成无刷新的 SPA 导航。
全局配置链接激活类
active-class与exact-active-class的默认值都可以在创建路由时全局覆盖,避免每个链接重复书写:
const router = new VueRouter({ mode: 'history', linkActiveClass: 'nav-item-active', linkExactActiveClass: 'nav-item-exact-active', routes: [ { path: '/', component: Home }, { path: '/about', component: About } ] })对应的选项类型声明位于 types/router.d.ts:linkActiveClass与linkExactActiveClass均为可选string,未提供时默认应用router-link-active/router-link-exact-active。源码中读取这两个全局选项的位置在 src/components/link.js。
小结
<router-link>是 vue-router 面向模板的导航入口,其价值在于:跨 History / Hash 模式行为一致、拦截点击避免整页刷新、自动兼容base配置,并通过to/replace/append/tag/exact/active-class/exact-active-class/event等 props 覆盖了绝大多数导航与高亮场景。想要深入验证文中行为,可运行仓库示例(npm run dev后访问 active-links 页面,配置见 examples/server.js),或阅读 examples/active-links/app.js 中覆盖了包含匹配、精确匹配、重定向、命名路由、query/hash 等边界情况的完整示例。
- 前端
- 路由
【免费下载链接】vue-router
🚦 The official router for Vue 2
相关推荐
Cordis Loader深度教程:YAML声明式插件加载的艺术
Cordis Loader深度教程:YAML声明式插件加载的艺术 Cordis Loader 是 Cordis 框架的官方插件加载器,它让 YAML 声明式插件
前端路由TanStack Router Link 组件详解:类型化 Props、激活态判定与预加载的源码级解析
TanStack Router Link 组件详解:类型化 Props、激活态判定与预加载的源码级解析 本篇基于 TanStack Router(本仓库)的官方
前端路由SSR如何用CSV.swift轻松解析CSV文件?5分钟快速上手教程
如何用CSV.swift轻松解析CSV文件?5分钟快速上手教程 CSV.swift是一款用Swift编写的高效CSV文件读写库,能帮助开发者轻松处理逗号分隔值文
前端路由
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考