- 前端
- 路由
【免费下载链接】vue-router
🚦 The official router for Vue 2
本篇技术指南以 Vue Router 2(本仓库vu/vue-router)官方文档《Options de construction du routeur》(路由构造选项)为骨架,系统讲解new VueRouter(options)中全部构造选项:routes、mode、base、linkActiveClass、linkExactActiveClass、scrollBehavior、parseQuery/stringifyQuery与fallback。读完本文,你将能独立完成一个生产级 Vue 2 应用的路由器初始化——包括多模式选型、子应用挂载路径、导航链接高亮、滚动位置恢复与查询串定制,并能对照 src/router.js 源码理解每个选项在底层是如何被消费的。
一、构造选项总览:一个对象驱动整个路由生命周期
Vue Router 2 的路由器实例通过构造函数创建,其签名与选项声明可以在 types/router.d.ts 的RouterOptions接口中看到:routes、mode、fallback、base、linkActiveClass、linkExactActiveClass、parseQuery、stringifyQuery、scrollBehavior共九个可选字段。
在 src/router.js 的构造函数中,这些选项被依次消费:
constructor (options: RouterOptions = {}) { this.options = options this.matcher = createMatcher(options.routes || [], this) // ① 路由表 → 匹配器 let mode = options.mode || 'hash' // ② 模式解析与降级 this.fallback = mode === 'history' && !supportsPushState && options.fallback !== false if (this.fallback) mode = 'hash' if (!inBrowser) mode = 'abstract' // ③ 无浏览器 API 强制 abstract switch (mode) { // ④ 实例化对应 History case 'history': this.history = new HTML5History(this, options.base); break case 'hash': this.history = new HashHistory(this, options.base, this.fallback); break case 'abstract':this.history = new AbstractHistory(this, options.base); break } }可以看到:routes先行构建 matcher,随后mode经过"默认值 → history 降级 → 环境强制"三重裁决,最终落到HTML5History/HashHistory/AbstractHistory三个具体实现(分别位于 src/history/html5.js、src/history/hash.js、src/history/abstract.js),而base则原样透传给这些 History 实例。理解这条调用链,后续每个选项的语义就一目了然。
二、routes:路由表与 RouteConfig 完整字段
routes是唯一必填的核心选项,类型为Array<RouteConfig>。官方文档给出的完整类型声明如下:
declare type RouteConfig = { path: string; component?: Component; name?: string; // pour les routes nommées(命名路由) components?: { [name: string]: Component }; // pour les vues nommées(命名视图) redirect?: string | Location | Function; props?: boolean | string | Function; alias?: string | Array<string>; children?: Array<RouteConfig>; // pour les routes imbriquées(嵌套路由) beforeEnter?: (to: Route, from: Route, next: Function) => void; meta?: any; // 2.6.0+ caseSensitive?: boolean; // 是否大小写敏感匹配(默认: false) pathToRegexpOptions?: Object; // 传给 path-to-regexp 编译正则的选项 }各字段作用与实战要点:
| 字段 | 类型 | 说明 |
|---|---|---|
path | string | 路由路径,必填。顶层路由必须以/开头,否则开发环境下 src/create-route-map.js 会发出 "Non-nested routes must include a leading slash character" 警告;非严格模式下末尾/会被自动去除(见下方normalizePath) |
component | Component | 单组件时使用;源码中与components合并为{ default: route.component }的命名视图形态 |
name | string | 路由命名,用于router.push({ name: '...' })与命名路由跳转 |
components | Object | 命名视图,key 对应<router-view name="..."> |
redirect | string \| Location \| Function | 重定向目标;函数形式可基于目标路由做动态重定向 |
props | boolean \| string \| Function | 将路由参数作为 props 传给组件(布尔/对象/函数三种形态) |
alias | string \| Array<string> | 路径别名,可多个;别名指向同一记录,URL 不变 |
children | Array<RouteConfig> | 嵌套子路由,子路径会与父路径拼接 |
beforeEnter | Function | 进入该路由的守卫,(to, from, next)签名 |
meta | any | 任意元数据,常用于配合导航守卫做权限、标题等标记 |
caseSensitive | boolean | 2.6.0+,大小写敏感匹配,默认false |
pathToRegexpOptions | Object | 2.6.0+,透传给path-to-regexp的编译选项 |
底层实现印证:在 src/create-route-map.js 的addRouteRecord中,caseSensitive会被直接映射为pathToRegexpOptions.sensitive,最终与pathToRegexpOptions一起传入Regexp(path, [], pathToRegexpOptions)编译正则;strict选项则控制normalizePath是否去除末尾斜杠。也就是说,caseSensitive本质是pathToRegexpOptions.sensitive的便捷写法。此外,alias会以"路径别名"的形式递归注册为独立记录(matchAs指向原记录),name重复时开发环境会告警,这些细节都可以在源码中找到对应实现。
一个覆盖多数字段的完整配置示例:
const routes = [ { path: '/user/:id', component: User, name: 'user', props: true, // 将 id 作为 prop 传给 User meta: { requiresAuth: true }, beforeEnter: (to, from, next) => { // 进入前的守卫逻辑 next() }, children: [ { path: 'profile', component: UserProfile }, // /user/:id/profile { path: 'posts', component: UserPosts } ] }, { path: '/admin', component: AdminLayout, caseSensitive: true, // 2.6.0+:大小写敏感 pathToRegexpOptions: { strict: true } // 2.6.0+:要求尾部斜杠精确匹配 }, { path: '*', component: NotFound } // 通配兜底,源码会将其排到匹配列表末尾 ]三、mode:hash / history / abstract 三种路由模式
- type:
string - 默认值:
"hash"(浏览器中)|"abstract"(Node.js 中) - 可选值:
"hash" | "history" | "abstract"
三种模式的官方定义:
hash:使用 URL 的 hash(#)部分完成路由。在所有 Vue 支持的浏览器中都能工作,包括不支持 HTML5 History API 的老浏览器。其实现见 src/history/hash.js:通过getHash()读取#后的路径,监听hashchange(不支持pushState时)或popstate事件驱动导航。history:依赖 HTML5 History API,且需要服务端配合配置(将未知路径回退到index.html),否则刷新页面会 404。完整说明见 HTML5 History 模式。实现见 src/history/html5.js,导航通过pushState/replaceState改写 URL,并监听popstate。abstract:在所有 JavaScript 环境中工作,例如 Node.js 服务端渲染。若检测不到任何浏览器 API,路由器会被自动强制切换到该模式。
源码级证据:从 src/router.js 可见,模式裁决分三步:
let mode = options.mode || 'hash' // 1. 未传时默认 hash this.fallback = mode === 'history' && !supportsPushState && options.fallback !== false if (this.fallback) mode = 'hash' // 2. 不支持 pushState 时 history → hash if (!inBrowser) mode = 'abstract' // 3. 无浏览器环境强制 abstract其中supportsPushState由 src/util/push-state.js 检测。abstract模式在 src/history/abstract.js 中用内存stack数组模拟历史栈,push/replace/go都不触碰window.location,这正是 SSR 与测试环境(如仓库 test/unit/specs/abstract-history.spec.js)能够运行路由的原因。
四、base:应用挂载的基础路径
- type:
string - 默认值:
"/"
当整个单页应用部署在某个子目录下(例如/app/)时,base必须设为"/app/"。此时:
history模式下,src/history/html5.js 的getLocation(base)会先剥离base前缀再参与匹配,避免base="/a"把/app误判为/a/pp(源码注释明确引用了 issue #3555);push/replace时又会把cleanPath(base + route.fullPath)写回地址栏;hash模式下,src/history/hash.js 的checkFallback与ensureSlash同样基于base计算。
const router = new VueRouter({ mode: 'history', base: '/app/', // 应用整体部署在 https://example.com/app/ 之下 routes: [ { path: '/', component: Home }, { path: '/about', component: About } ] })配置后访问https://example.com/app/about,路由匹配到/about,且<router-link :to="'/about'">无需再写/app前缀(详见 router-link 文档 中的说明)。
五、linkActiveClass 与 linkExactActiveClass:全局导航高亮类名
linkActiveClass:string,默认"router-link-active"。全局配置<router-link>的"包含匹配"激活类。linkExactActiveClass(2.5.0+):string,默认"router-link-exact-active"。全局配置"精确匹配"时的激活类。
两者的语义差异:activeClass只要当前路由包含目标路由(例如当前在/user/123/posts,指向/user/123的链接也处于激活态),exactActiveClass则要求完全相等。可以同时生效——一个链接可能同时挂两个类。
源码证据:在 src/components/link.js 的渲染逻辑中,<router-link>的类名计算为:
const globalActiveClass = router.options.linkActiveClass const globalExactActiveClass = router.options.linkExactActiveClass const activeClassFallback = globalActiveClass == null ? 'router-link-active' : globalActiveClass const exactActiveClassFallback = globalExactActiveClass == null ? 'router-link-exact-active' : globalExactActiveClass classes[exactActiveClass] = isSameRoute(current, compareTarget, this.exactPath) classes[activeClass] = this.exact || this.exactPath ? classes[exactActiveClass] : isIncludedRoute(current, compareTarget)即:精确激活由isSameRoute判定,包含激活由isIncludedRoute判定;若链接设置了exact或exactPath,则两类合一。组件自身的active-class/exact-active-classprop 优先级高于全局选项。
const router = new VueRouter({ linkActiveClass: 'nav-item--active', // 替换默认 router-link-active linkExactActiveClass: 'nav-item--exact-active' // 2.5.0+,替换默认 router-link-exact-active })六、scrollBehavior:自定义滚动位置恢复
- type:
Function
官方签名为:
type PositionDescriptor = { x: number, y: number } | { selector: string } | ?{} type scrollBehaviorHandler = ( to: Route, from: Route, savedPosition?: { x: number, y: number } ) => PositionDescriptor | Promise<PositionDescriptor>其中to/from是导航前后的路由对象;savedPosition仅在浏览器前进/后退(popstate)时存在,包含上次离开位置{ x, y }。返回{ x, y }滚动到坐标、返回{ selector: string }滚动到元素,返回空对象/false则不滚动,也可返回 Promise 延迟滚动。
完整理论说明见 滚动行为,仓库 examples/scroll-behavior 提供了可运行的示例应用。
源码证据:滚动逻辑集中在 src/util/scroll.js:
- 仅当
supportsPushState && expectScroll时才会注册滚动监听(src/history/html5.js),因此该功能依赖 History API; handleScroll在router.app.$nextTick中执行,等渲染完成后再滚动;- 返回值若带
then(Promise)则异步处理,支持selector通过document.querySelector定位元素,支持offset偏移与behavior平滑滚动(见scrollToPosition)。
const router = new VueRouter({ mode: 'history', scrollBehavior (to, from, savedPosition) { if (savedPosition) { return savedPosition // 前进/后退时恢复原位置 } else { return { x: 0, y: 0 } // 普通导航回到顶部 } } })进阶用法——滚动到带offset的元素并支持异步数据加载后滚动:
scrollBehavior (to, from, savedPosition) { if (to.hash) { return { selector: to.hash, offset: { x: 0, y: 80 } } } if (savedPosition) return savedPosition return new Promise(resolve => { fetchData().then(() => resolve({ x: 0, y: 0 })) }) }七、parseQuery 与 stringifyQuery:自定义查询串解析
2.4.0+
- type:
Function
分别用于定制"查询串 → 对象"与"对象 → 查询串"的转换,完全覆盖默认实现。适用于自定义查询参数格式、特殊编码规则等场景。
默认实现参考:仓库 src/util/query.js 中的parseQuery按&切分、=拆键值,重复键合并为数组;stringifyQuery将对象编码为查询串(undefined跳过、数组展开为多个key=value、null输出裸 key),且encode基于encodeURIComponent并额外转义!'()*、保留逗号,更贴近 RFC 3986。
const router = new VueRouter({ parseQuery (query) { // 自定义:例如把 'a;b;c' 解析成数组 const res = {} query.split('&').forEach(pair => { const [key, value] = pair.split('=') res[key] = res[key] ? [].concat(res[key], value) : value }) return res }, stringifyQuery (obj) { // 自定义序列化,注意不要以 '?' 开头(类型声明中明确要求) return Object.keys(obj) .map(key => `${key}=${encodeURIComponent(obj[key])}`) .join('&') } })需要注意:类型声明 types/router.d.ts 中写明stringifyQuery不应输出前导?;parseQuery与stringifyQuery必须成对配套,否则会出现解析与序列化不对称的问题。
八、fallback:history 不可用时的降级控制
2.6.0+
- type:
boolean - 默认值:
true
控制当浏览器不支持history.pushState时,路由器是否自动降级为hash模式。源码见 src/router.js:
this.fallback = mode === 'history' && !supportsPushState && options.fallback !== false if (this.fallback) { mode = 'hash' }将fallback显式设为false后,在 IE9 这类不支持 History API 的浏览器中,router-link的导航将退化为整页刷新(因为 hash 模式被禁用)。这一行为在服务端渲染(SSR)且需要兼容 IE9 的场景中有实际意义——hash 模式与 SSR 不兼容,此时宁可让链接退化为整页刷新,也要保持 history 语义。官方文档对此的说明是:
将
fallback设为false本质上会使router-link的导航在 IE9 中触发页面重新加载。当应用由服务端渲染且需要支持 IE9 时这很有用,因为 hash 模式无法与 SSR 配合。
// SSR + IE9 兼容场景 const router = new VueRouter({ mode: 'history', fallback: false // 2.6.0+,禁止自动降级到 hash })九、完整实战:一个生产级路由器初始化示例
将上述选项整合,一个典型的 Vue 2 生产应用初始化如下:
import Vue from 'vue' import VueRouter from 'vue-router' Vue.use(VueRouter) const router = new VueRouter({ mode: 'history', // 需要服务端回退配置 base: '/app/', // 部署子路径 linkActiveClass: 'nav--active', linkExactActiveClass: 'nav--exact-active', fallback: true, // 不支持 pushState 时自动降级 hash scrollBehavior (to, from, savedPosition) { return savedPosition || { x: 0, y: 0 } }, routes: [ { path: '/', name: 'home', component: Home }, { path: '/user/:id', name: 'user', component: User, props: true, meta: { requiresAuth: true }, children: [ { path: 'profile', component: UserProfile } ] }, { path: '*', component: NotFound } ] }) new Vue({ router, render: h => h(App) }).$mount('#app')小结
本文以官方《Options de construction du routeur》为骨架,完整覆盖了 Vue Router 2 构造器的全部九项选项:routes定义路由表与RouteConfig字段语义(含 2.6.0 的caseSensitive/pathToRegexpOptions),mode三种模式的选型与自动降级裁决链,base的子路径部署,两个链接激活类名的全局配置与精确/包含匹配差异,scrollBehavior的滚动恢复与元素定位,parseQuery/stringifyQuery的查询串定制,以及fallback在 IE9 + SSR 场景下的降级控制。每个选项都能在 src/router.js、src/history 目录、src/create-route-map.js、src/util/query.js、src/util/scroll.js 与 src/components/link.js 中找到对应的实现证据,类型声明则以 types/router.d.ts 为准。配置时可对照 测试用例 与 examples 目录验证行为,确保每个选项都用在正确的场景中。
- 前端
- 路由
【免费下载链接】vue-router
🚦 The official router for Vue 2
相关推荐
Vue Router 2 构造器选项(Router Construction Options)完整指南:routes、mode、base 与 scrollBehavior 深度解析
Vue Router 2 构造器选项(Router Construction Options)完整指南:routes、mode、base 与 scrollBeh
前端路由vue-router 构造选项完全指南:从 routes 配置到 mode、scrollBehavior 与 fallback 的底层实现解析
vue router 构造选项完全指南:从 routes 配置到 mode、scrollBehavior 与 fallback 的底层实现解析 导读 new V
前端路由Vue Router 2 命名路由(Named Routes)完全指南:配置、跳转与源码级原理
Vue Router 2 命名路由(Named Routes)完全指南:配置、跳转与源码级原理 命名路由是 Vue Router(本项目为 Vue 2 官方路由
前端路由
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考