Vue Router 2 构造选项全解析:routes、mode、base 与 scrollBehavior 配置指南
2026/9/21 7:26:17 网站建设 项目流程
  • 前端
  • 路由

【免费下载链接】vue-router

🚦 The official router for Vue 2

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

本篇技术指南以 Vue Router 2(本仓库vu/vue-router)官方文档《Options de construction du routeur》(路由构造选项)为骨架,系统讲解new VueRouter(options)中全部构造选项:routesmodebaselinkActiveClasslinkExactActiveClassscrollBehaviorparseQuery/stringifyQueryfallback。读完本文,你将能独立完成一个生产级 Vue 2 应用的路由器初始化——包括多模式选型、子应用挂载路径、导航链接高亮、滚动位置恢复与查询串定制,并能对照 src/router.js 源码理解每个选项在底层是如何被消费的。

一、构造选项总览:一个对象驱动整个路由生命周期

Vue Router 2 的路由器实例通过构造函数创建,其签名与选项声明可以在 types/router.d.ts 的RouterOptions接口中看到:routesmodefallbackbaselinkActiveClasslinkExactActiveClassparseQuerystringifyQueryscrollBehavior共九个可选字段。

在 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 编译正则的选项 }

各字段作用与实战要点:

字段类型说明
pathstring路由路径,必填。顶层路由必须以/开头,否则开发环境下 src/create-route-map.js 会发出 "Non-nested routes must include a leading slash character" 警告;非严格模式下末尾/会被自动去除(见下方normalizePath
componentComponent单组件时使用;源码中与components合并为{ default: route.component }的命名视图形态
namestring路由命名,用于router.push({ name: '...' })与命名路由跳转
componentsObject命名视图,key 对应<router-view name="...">
redirectstring \| Location \| Function重定向目标;函数形式可基于目标路由做动态重定向
propsboolean \| string \| Function将路由参数作为 props 传给组件(布尔/对象/函数三种形态)
aliasstring \| Array<string>路径别名,可多个;别名指向同一记录,URL 不变
childrenArray<RouteConfig>嵌套子路由,子路径会与父路径拼接
beforeEnterFunction进入该路由的守卫,(to, from, next)签名
metaany任意元数据,常用于配合导航守卫做权限、标题等标记
caseSensitiveboolean2.6.0+,大小写敏感匹配,默认false
pathToRegexpOptionsObject2.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 三种路由模式

  • typestring
  • 默认值"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:应用挂载的基础路径

  • typestring
  • 默认值"/"

当整个单页应用部署在某个子目录下(例如/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 的checkFallbackensureSlash同样基于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:全局导航高亮类名

  • linkActiveClassstring,默认"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判定;若链接设置了exactexactPath,则两类合一。组件自身的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:自定义滚动位置恢复

  • typeFunction

官方签名为:

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;
  • handleScrollrouter.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+

  • typeFunction

分别用于定制"查询串 → 对象"与"对象 → 查询串"的转换,完全覆盖默认实现。适用于自定义查询参数格式、特殊编码规则等场景。

默认实现参考:仓库 src/util/query.js 中的parseQuery&切分、=拆键值,重复键合并为数组;stringifyQuery将对象编码为查询串(undefined跳过、数组展开为多个key=valuenull输出裸 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不应输出前导?parseQuerystringifyQuery必须成对配套,否则会出现解析与序列化不对称的问题。

八、fallback:history 不可用时的降级控制

2.6.0+

  • typeboolean
  • 默认值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

项目地址:https://gitcode.com/gh_mirrors/vu/vue-router
点击查看免费下载
上一篇:功能描述
下一篇:Optimum项目中的BetterTransformer兼容性问题解析

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

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

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

立即咨询