VueRouter
[TOC]
索引
HTML5
History
- history.length:
number
,只读
,返回一个表示会话历史中的条目数量的整数,包括当前加载的页面。 - history.state:
State
,用于访问/操作浏览器历史记录中的状态对象。主要用于SPA中的导航操作。 - history.back():
()
,用于让浏览器回到历史记录中的前一个页面。可理解为模拟用户点击浏览器的“后退”按钮。 - history.forward():
()
,用于让浏览器前进到历史记录中的下一个页面。可理解为模拟用户点击浏览器的“前进”按钮。 - history.go():
(delta)
,用于在浏览器历史记录栈中进行前进或后退操作。 - history.pushState():
(state,title?,url?)
,用于将一个新的历史记录条目添加到浏览器的历史记录栈中,而不会刷新页面。 - history.replaceState():
(state,title?,url?)
,用于替换当前浏览器历史记录中的条目。 - onpopstate:
(event)=>void
,是一个浏览器的事件监听器,用于监听浏览器历史记录的变化。
HTML5
History
length
history.length:number
,只读
,返回一个表示会话历史中的条目数量的整数,包括当前加载的页面。
state
history.state:State
,用于访问/操作浏览器历史记录中的状态对象。主要用于SPA中的导航操作。
- 返回:
- state:
State | null
,返回当前页面的状态对象。如果没有则返回null。
back()
history.back():()
,用于让浏览器回到历史记录中的前一个页面。可理解为模拟用户点击浏览器的“后退”按钮。
forward()
history.forward():()
,用于让浏览器前进到历史记录中的下一个页面。可理解为模拟用户点击浏览器的“前进”按钮。
go()
history.go():(delta)
,用于在浏览器历史记录栈中进行前进或后退操作。
- delta:
number
,表示在浏览器历史记录栈中的偏移量。正数
:浏览器会前进delta个页面。负数
:浏览器会后退delta个页面。0
:浏览器会刷新当前页面。超出范围
:超出历史栈的范围,浏览器不会做任何跳转,页面保持不变。
pushState()
history.pushState():(state,title?,url?)
,用于将一个新的历史记录条目添加到浏览器的历史记录栈中,而不会刷新页面。
state:
object
,包含有关该历史条目的信息的对象。title?:
string
,新的历史记录条目的标题。很少用到,常设为""
。url?:
string
,新的历史记录条目的 URL。必须是同一域名下的有效路径。示例:
- 基本用法
js// state 对象包含当前视图的信息 const state = { page: 1 }; const title = ""; // 通常是空字符串 const url = "/page1"; // 将新的历史记录条目添加到浏览器历史记录栈 history.pushState(state, title, url);
- 结合popstate 事件
js// 监听 popstate 事件 window.addEventListener("popstate", function(event) { console.log("State changed:", event.state); // 根据新的 state 进行页面更新 updatePageView(event.state.section); }); // 通过 pushState 改变历史记录 history.pushState({ section: "home" }, "", "/home"); // 模拟用户点击浏览器的后退按钮 history.back();
replaceState()
history.replaceState():(state,title?,url?)
,用于替换当前浏览器历史记录中的条目。
state:
object
,包含有关该历史条目的信息的对象。title?:
string
,新的历史记录条目的标题。很少用到,常设为""
。url?:
string
,新的历史记录条目的 URL。必须是同一域名下的有效路径。特性:
- 对比pushState():
- pushState()会添加新的历史记录条目,会增加一个新的条目。
- replaceState()会替换当前历史记录条目,不会改变历史栈的长度。
- 对比pushState():
示例:
- 替换当前历史记录的URL
js// 当前 URL 是 "/page1",我们想将它替换为 "/page2" const state = { page: 2 }; const title = ""; const url = "/page2"; // 替换当前的历史记录条目 history.replaceState(state, title, url);
- 结合popstate 事件
js// 监听 popstate 事件 window.addEventListener("popstate", function(event) { console.log("State changed:", event.state); // 根据新的 state 进行页面更新 updatePageView(event.state.section); }); // 替换历史记录 history.replaceState({ section: "home" }, "", "/home");
onpopstate
onpopstate:(event)=>void
,是一个浏览器的事件监听器,用于监听浏览器历史记录的变化。
- event:
{type,target,state}
,事件触发时传递的event对象。- state:
object
,与当前历史条目相关联的状态对象。
- state:
- 语法:
- 触发条件:当用户通过浏览器的“后退”/“前进”按钮导航,或通过 pushState()/replaceState() 方法修改历史记录时触发。
VueRouter
组件
<router-link>
<router-link>:to replace? custom? active-class? exact-active-class? v-slot?
,是 Vue Router 的导航组件,用于在SPA中生成可点击的路由链接,默认渲染为a标签。核心作用是实现无刷新页面切换,并自动处理路由激活状态。
to:
string|object
,指定目标路由的路径或路由对象。replace?:
boolean
,默认:false
,导航时替换当前历史记录。custom?:
boolean
,默认:false
,禁用默认a标签渲染,完全自定义内容,需手动实现路由跳转。active-class?:
string
,默认:router-link-active
,当目标路由是当前路由的子路径时激活 CSS 类名。exact-active-class?:
string
,默认:router-link-exact-active
,仅当目标路由与当前路由完全匹配时激活 CSS 类名。v-slot?:
{href?,route?,navigate?,isActive?,isExactActive?}
,通过 v-slot 可完全自定义链接内容和行为。- href?:
string
,解析后的 URL,可用于原生a标签。 - route?:
object
,解析后的规范化路由对象。 - navigate?:
function
,触发导航的函数。 - isActive?:
boolean
,是否匹配当前路由。 - isExactActive?:
boolean
,是否严格匹配当前路由。
- href?:
语法:
参数to的类型:
- 字符串形式:
html<router-link to="/home">首页</router-link>
- 对象形式:动态路径或带参数。
html<router-link :to="{ path: '/user', query: { id: 1 } }">用户</router-link> <!-- 结果:/user?id=1 --> <router-link :to="{ name: 'profile', params: { username: 'alice' } }">个人资料</router-link> <!-- 结果:/profile/alice -->
参数v-slot:完全自定义链接内容和行为。
html<router-link to="/dashboard" v-slot="{ href, isActive }"> <a :href="href" :class="{ active: isActive }">控制台</a> </router-link>
路由激活状态:
html<!-- 当前路由为 /user/profile --> <router-link to="/user">用户中心</router-link> <!-- 激活类:router-link-active --> <router-link to="/user/profile">个人资料</router-link> <!-- 激活类:router-link-active + router-link-exact-active -->
常见用途:
基本导航:
html<router-link to="/">首页</router-link> <router-link :to="{ name: 'user', params: { id: 1 } }">用户 1</router-link>
带查询参数:
html<router-link :to="{ path: '/search', query: { q: 'vue' } }">搜索 Vue</router-link> <!-- 结果:/search?q=vue -->
自定义激活样式:
html<router-link to="/contact" active-class="active-link" exact-active-class="exact-active-link" > 联系我们 </router-link>
动态路径与参数:
html<!-- /posts/123 --> <router-link :to="`/posts/${postId}`">文章详情</router-link> <!-- /product/123?from=home --> <router-link :to="{ name: 'product', params: { id: product.id }, query: { from: 'home' } }"> {{ product.name }} </router-link>
导航守卫与事件:@
html<router-link to="/checkout" @click.native.prevent="handleClick" :event="isLoggedIn ? 'click' : ''" > 结算 </router-link>
注意事项:
- 避免在to中混用path和name:优先使用 name 以解耦路径。
- 动态参数需事先占位:使用 params 时,目标路由必须定义对应的参数占位符,如
/user/:id
。 - 慎用replace:替换历史记录后用户无法通过浏览器后退按钮返回。
- 性能优化:频繁变化的动态路由可结合
<keep-alive>
缓存组件状态。
<router-view>
<router-view>:name?,v-slot?,
,是 Vue Router 的核心组件,用于在SPA中渲染当前路由匹配的组件。它相当于一个动态占位符,根据路由规则切换显示内容。
name?:
string
,支持多视图渲染,需在路由配置中定义 components 对象。v-slot?:
{Component}
,暴露一个插槽,用来渲染路由组件。语法:
渲染规则:
- 根据当前路由路径,自动匹配并渲染路由配置中对应的组件。
- 支持嵌套路由,通过层级 router-view 实现父子组件嵌套渲染。
命名视图:通过 name 属性支持多视图渲染,需在路由配置中定义 components 对象。
- 1、布局组件中定义多个命名视图
html<template> <div> <router-view name="header"></router-view> <router-view></router-view> <!-- 默认 name: default --> <router-view name="footer"></router-view> </div> </template>
- 2、路由配置
jsconst routes = [ { path: '/', components: { default: Home, // 默认视图渲染 Home 组件 header: Header, // 命名视图 header 渲染 Header 组件 footer: Footer // 命名视图 footer 渲染 Footer 组件 } } ];
嵌套路由:通过嵌套 router-view 实现多层组件结构。
- 1、路由配置
jsconst routes = [ { path: '/user/:id', component: UserLayout, // 父组件 children: [ { path: 'profile', component: UserProfile, // 子组件渲染在 UserLayout 的 <router-view> 中 }, { path: 'settings', component: UserSettings } ] } ];
- 2、父组件模板
html<!-- UserLayout.vue --> <template> <div> <h2>用户中心</h2> <router-view></router-view> <!-- 子路由组件在此渲染 --> </div> </template>
路由插槽:暴露一个插槽,用来渲染路由组件。当想要获得其他功能时,插槽提供了额外的扩展性。
html<router-view v-slot="{ Component }"> <component :is="Component" /> </router-view> <!-- 等价于 <router-view /> -->
过渡动画:用 transition 包裹 router-view 实现路由切换动画。
html<template> <router-view v-slot="{ Component }"> <transition name="fade" mode="out-in"> <component :is="Component" /> </transition> </router-view> </template> <style> .fade-enter-active, .fade-leave-active { transition: opacity 0.3s; } .fade-enter-from, .fade-leave-to { opacity: 0; } </style>
组件缓存:用 keep-alive 包裹 router-view 缓存组件状态。
html<keep-alive> <router-view></router-view> </keep-alive>
传递Props:通过路由配置向组件传递 Props
jsconst routes = [ { path: '/user/:id', component: UserProfile, props: true // 将路由 params 作为 props 传递(如 :id → props.id) }, { path: '/about', component: About, props: { staticData: 'Hello' } // 传递静态对象 }, { path: '/dynamic', component: Dynamic, props: (route) => ({ query: route.query.q }) // 函数模式动态生成 props } ];
路由元信息:
- 1、结合路由元信息 meta 控制视图逻辑。
jsconst routes = [ { path: '/admin', component: AdminDashboard, meta: { requiresAuth: true } } ];
- 2、在组件中访问元信息。
jsexport default { mounted() { if (this.$route.meta.requiresAuth) { // 检查权限逻辑 } } }
注意事项:
- 唯一根元素:每个router-view对应路由配置中的一个组件,确保组件模板有唯一根元素,Vue3支持多根节点。
- 命名视图匹配:若路由配置未提供对应名称的组件,命名视图区域将渲染为空。
- 性能优化:
- 使用 keep-alive 缓存高频访问的页面。
- 按需加载路由组件/异步组件提升首屏速度。
<>
<>
<>
<>
<>
<>
Router
useRouter()【
createRouter()@4
createRouter():({history,routes,scrollBehavior?,...})
,是 VueRouter4 中用于创建路由实例的核心函数。替代了 VueRouter3 的 new VueRouter()。
history:
RouterHistory
,指定路由的历史模式。有以下三种内置模式:- createWebHistory():
(base?)
,HTML5模式,无哈希。 - createWebHashHistory():
(base?)
,哈希模式,兼容旧浏览器。 - createMemoryHistory():
(base?)
,内存模式,SSR或测试环境使用。
- createWebHistory():
routes:
RouteRecordRaw[]
,定义路由配置的数组。路由对象 RouteRecordRaw 包含以下常见属性:- path:
string
,路由路径,支持动态参数,如/user/:id
。 - name:
string
,路由唯一名称,用于编程式导航。 - component:
Component|()=>import()
,对应组件或异步组件函数。 - components:
object
,命名视图配置,用于多视图场景。 - redirect:
string|object
,重定向目标。 - children:
RouteRecordRaw[]
,嵌套路由配置。 - meta:
any
,路由元信息,用于权限控制等。 - props:
boolean|object|function
,向组件传递 Props。
- path:
scrollBehavior?:
(to,from,savedPosition)=>PositionResult|Promise
,控制页面滚动行为。to:
string|object
,目标路由地址。from:
string|object
,来源路由地址。savedPosition:
Position|null
,浏览器前进/后退时记录的滚动位置。返回:
position:
PositionResult|Promise
,可指定滚动位置({ top: number, left: number }
)、滚动到指定选择器({ selector: string }
)或保持原位(false
)。
linkActiveClass?:
string
,默认:router-link-active
,当目标路由是当前路由的子路径时激活 CSS 类名。linkExactActiveClass?:
string
,默认:router-link-exact-active
,仅当目标路由与当前路由完全匹配时激活 CSS 类名。parseQuery:
(search)=>Record<string,any>
,自定义查询参数 query 的解析函数。stringifyQuery:
(query)=>string
,自定义查询参数 query 的序列化函数。fallback:
boolean
,默认:true
,在不支持 history.pushState 的浏览器中,是否回退到哈希模式返回:
router:
Router
,返回一个路由实例,包含以下核心方法/属性:【TODO:添加链接】- addRoute():
()
,动态添加路由。 - removeRoute():
()
,移除路由。 - hasRoute():
()
,检查路由是否存在。 - getRoutes():
()
,获取当前路由配置。 - beforeEach():
()
,全局导航守卫-前置。 - afterEach():
()
,全局导航守卫-后置。 - push():
()
,编程式导航-前进。 - replace():
()
,编程式导航-替换。
- addRoute():
语法:
控制页面滚动行为:
jsscrollBehavior(to, from, savedPosition) { if (savedPosition) { return savedPosition; // 恢复历史滚动位置 } else if (to.hash) { return { selector: to.hash }; // 滚动到锚点 } else { return { top: 0 }; // 滚动到顶部 } }
使用qs库处理嵌套对象:
jsimport qs from 'qs'; parseQuery: (search) => qs.parse(search, { ignoreQueryPrefix: true }), stringifyQuery: (query) => qs.stringify(query),
注意事项:
- 路由懒加载:使用
() => import()
语法实现组件按需加载。 - TS支持:确保定义路由时使用
RouteRecordRaw
类型,以获得类型检查和自动补全。 - 动态路由:通过
router.addRoute()
可在运行时动态添加路由。
- 路由懒加载:使用
示例:完整配置
jsimport { createRouter, createWebHistory } from 'vue-router'; import Home from '../views/Home.vue'; const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), // 基路径 routes: [ { path: '/', name: 'Home', component: Home, meta: { title: '首页' } }, { path: '/about', name: 'About', component: () => import('../views/About.vue'), meta: { requiresAuth: true } } ], scrollBehavior(to, from, savedPosition) { return savedPosition || { top: 0 }; }, linkActiveClass: 'active-link', linkExactActiveClass: 'exact-active-link' }); export default router;
createWebHashHistory()
createWebHashHistory():(base?)
,用于创建基于 哈希模式(Hash Mode) 的路由历史记录。
- base?:
string
,默认:''
,表示应用的基础路径,所有路由将相对于该路径解析。 - 返回:
- history:
RouterHistory
,返回一个RouterHistory对象,用于 Vue Router 的配置。 - 语法:
- base规范化:
- 自动添加前导斜杠,如
my-app
→/my-app
。 - 尾部斜杠会被保留,如传入
/my-app/
则保持为/my-app/
。
- 自动添加前导斜杠,如
- base设置路由前缀:部署时可以通过base设置路由前缀,如
/my-app/
。
- base规范化:
- 特性:
- 哈希模式特点:
- URL 结构: 路由路径位于
#
之后,如https://example.com/#/about
。 - 无服务器配置要求: 哈希变化不会触发页面请求,服务器只需返回单个 HTML 文件。
- 监听机制: 通过
hashchange
事件响应路由变化,兼容性良好。
- URL 结构: 路由路径位于
- 哈希模式特点:
- 示例:设置路由前缀js
import { createRouter, createWebHashHistory } from 'vue-router' const router = createRouter({ history: createWebHashHistory('/my-app/'), // 路由前缀为 /my-app/ routes: [ // 定义路由... ] }) // 部署后路径URL为:https://example.com/my-app/#/home
createWebHistory()
createWebHistory():(base?)
,用于创建基于 HTML5 History API 的路由历史记录,也称为“历史模式”。
base?:
string
,默认:''
,表示应用的基础路径,所有路由将相对于该路径解析。返回:
history:
RouterHistory
,返回一个RouterHistory对象,用于 Vue Router 的配置。语法:
base规范化:
- 自动添加前导斜杠,如
my-app
→/my-app
。 - 尾部斜杠会被保留,如传入
/my-app/
则保持为/my-app/
。
- 自动添加前导斜杠,如
base设置路由前缀:部署时可以通过base设置路由前缀,如
/my-app/
。服务器配置:
- Nginx:
shlocation / { try_files $uri $uri/ /index.html; }
- Apache:
shRewriteEngine On RewriteBase / RewriteRule ^index\.html$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.html [L]
特性:
- 历史模式特点:
- URL结构:URL 路径无
#
,如https://example.com/about
,更符合标准 URL 规范。 - 依赖HTML5 History API:使用 pushState() 和 replaceState() 操作浏览历史记录,兼容现代浏览器。
- 服务器配置要求:直接访问子路径如
https://example.com/about
时,需确保服务器返回应用入口文件如index.html
,否则会触发 404 错误。 - SPA友好:适合SPA,但需配合服务器配置。
- URL结构:URL 路径无
- 历史模式特点:
注意事项:
- 部署路径匹配:若应用部署在子目录,如
/my-app/
,需同时配置 base 参数和服务器路径规则。 - 兼容性:不支持 IE9 及以下浏览器,需 Polyfill 或降级为哈希模式。
- 开发环境:Vue CLI 或 Vite 的开发服务器已默认支持 History 模式,无需额外配置。
- 部署路径匹配:若应用部署在子目录,如
示例:
jsimport { createRouter, createWebHistory } from 'vue-router' const router = createRouter({ history: createWebHistory('/my-app/'), // 基础路径为 /my-app/ routes: [ { path: '/', component: Home }, { path: '/about', component: About } ] }) // 部署后路径URL为:https://example.com/my-app/home
addRoute()【
removeRoute()【
hasRoute()【
getRoutes()【
beforeEach()【
afterEach()【
push()【
replace()【
Route
useRoute()【
SSR
createMemoryHistory()
createMemoryHistory():()
,用于创建一个基于 内存 的路由历史记录,也称为“抽象模式”。
base?:
string
,默认:''
,表示应用的基础路径,所有路由将相对于该路径解析。返回:
history:
RouterHistory
,返回一个RouterHistory对象,用于 Vue Router 的配置。语法:
base规范化:
- 自动添加前导斜杠,如
my-app
→/my-app
。 - 尾部斜杠会被保留,如传入
/my-app/
则保持为/my-app/
。
- 自动添加前导斜杠,如
base设置路由前缀:部署时可以通过base设置路由前缀,如
/my-app/
。自定义初始状态:可通过选项对象初始化内存历史记录的初始路径和状态。
jsconst history = createMemoryHistory({ base: '/my-app/', initialEntries: ['/home'], // 初始路径 initialState: { user: 'admin' } // 附加初始状态(可通过 router.currentRoute.value.state 访问) })
特性:
- 内存模式特点:
- 无URL依赖:路由状态完全存储在内存中,不修改浏览器 URL,适合无 DOM 的环境如 Node.js。
- 手动导航控制:需通过编程式导航,如
router.push()
或router.replace()
管理路由跳转。 - SSR友好:服务端渲染时,每个请求需创建一个独立的内存历史实例,避免状态污染。
- 轻量且隔离:不同实例之间的路由状态互不影响,适合多用户并发场景。
- 内存模式特点:
常见用途:
基本配置:
jsimport { createRouter, createMemoryHistory } from 'vue-router' const router = createRouter({ history: createMemoryHistory('/my-app/'), // 基础路径为 /my-app/ routes: [ { path: '/', component: Home }, { path: '/about', component: About } ] })
在SSR中的应用:
js// 服务端代码(Node.js) export function createSSRRouter() { return createRouter({ history: createMemoryHistory(), routes: [ // 定义路由... ] }) }
测试环境中模拟路由:
js// 单元测试示例(Jest/Vitest) test('navigates to about page', async () => { const history = createMemoryHistory() const router = createRouter({ history, routes }) await router.push('/about') expect(router.currentRoute.value.path).toBe('/about') })
注意事项:
- 不适用于浏览器环境:在浏览器中使用时,用户无法通过地址栏直接输入路径或使用前进/后退按钮导航。
- 需手动同步状态:若需要将路由状态传递到客户端,如 SSR 脱水/注水,需显式处理序列化和反序列化。