vue-router 2.x 中 `<router-link>` 组件完整指南:Props、激活类与源码实现解析
2026/9/21 15:51:24 网站建设 项目流程
  • 前端
  • 路由

【免费下载链接】vue-router

🚦 The official router for Vue 2

项目地址:https://gitcode.com/gh_mirrors/vu/vue-router
点击查看免费下载

<router-link>是 vue-router(Vue 2 官方路由)中用于在启用路由的应用里触发用户导航的核心声明式组件:它以toprop 指定目标位置,默认渲染为带正确href<a>标签,并能在目标路由激活时自动为链接添加 active CSS 类。阅读本文后,你将掌握<router-link>全部 props 的用法与默认值、active 类“包含匹配”与“精确匹配”的差异,以及其在 src/components/link.js 中的底层实现原理(如router.resolveisIncludedRouteguardEvent)。

<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>的根本原因:

  1. 跨模式行为一致:无论路由器工作在 HTML5 History 模式还是 Hash 模式,<router-link>都以相同方式工作。当你决定切换模式,或路由器因 IE9 等环境自动回退到 Hash 模式时,模板代码完全无需改动。
  2. 阻止浏览器整页刷新:在 HTML5 History 模式下,<router-link>会拦截点击事件,避免浏览器执行默认行为导致页面重新加载。这一点在源码guardEvent中有完整的实现(见下文“点击拦截的实现”一节),它通过e.preventDefault()阻断默认跳转,再把导航交给路由内部的push/replace流程。
  3. 自动处理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)会在开发环境对tageventprops 给出弃用警告,提示它们在 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 中的isIncludedRouteisSameRoute实现(详见下文“激活类的判定原理”)。

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-pathboolean,默认false。仅用 URL 的path部分做精确匹配,忽略queryhash。例如<router-link to="/search" exact-path>/search?page=2/search#filters下同样激活。对应类型声明见 types/router.d.ts。
  • exact-path-active-classstring,默认"router-link-exact-path-active",可通过路由构造选项linkExactPathActiveClass全局配置。
  • aria-current-value'page' | 'step' | 'location' | 'date' | 'time' | 'true' | 'false',默认"page"。在链接精确激活时设置到aria-current属性上,默认值page通常是最佳选择,类型定义见 types/router.d.ts。
  • customboolean,默认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>上。这个行为与源码中“taga时查找内部首个<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,核心逻辑如下:

  1. 通过router.resolve(this.to, current, this.append)得到locationroutehref(src/components/link.js);
  2. 读取全局配置router.options.linkActiveClasslinkExactActiveClass,若未配置则回退到"router-link-active"/"router-link-exact-active";组件自身的activeClass/exactActiveClassprop 优先级最高(src/components/link.js);
  3. 处理重定向:若目标路由存在redirectedFrom,会先基于它构造对比目标,保证重定向前的链接也能正确高亮(src/components/link.js);
  4. 精确激活类exactActiveClassisSameRoute(current, compareTarget, this.exactPath)决定;非精确的包含类activeClassexactexactPath开启时直接取精确匹配结果,否则由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交给路由导航:

  • 按住修饰键(metaKeyaltKeyctrlKeyshiftKey)时不拦截——保留浏览器在新标签页打开链接的能力;
  • 事件已被preventDefault()调用过时不重复处理;
  • 非左键点击(如右键)不处理;
  • target="_blank"的链接不拦截。

拦截成功后,handler 根据replace调用router.replacerouter.push(src/components/link.js),从而完成无刷新的 SPA 导航。

全局配置链接激活类

active-classexact-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:linkActiveClasslinkExactActiveClass均为可选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

项目地址:https://gitcode.com/gh_mirrors/vu/vue-router
点击查看免费下载
上一篇:Amulet Map Editor:打破Minecraft版本壁垒的终极创作工具箱
下一篇:FastJSON多版本共存:ClassLoader隔离解决依赖冲突问题

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询