vue-router源码浅析
# vue router 源码浅析
# 概述
# 常用属性介绍
# RouterLink
RouterLink
实际上就是通过 vue 的defineComponent
方法定义的组件,创建一个<a>
标签, 该组件内部会调用useLink()
方法,这个useLink
会根据参数 props 创建响应式的链接属性,以及处理链接事件
# RouterView
RouterView
同上,也是 vue 的defineComponent
定义的组件
# 常用 API 介绍
# createRouter
createRouter
方法用来创建一个路由实例,该方法接收一个参数,该参数是一个对象,该对象用来配置路由实例,通常如下创建
const router = createRouter({
history: createWebHashHistory(),
routes,
});
2
3
4
createRouter
首先就会调用createRouterMatcher
方法,返回的值标记为matcher
# createRouterMatch
createRouterMatch
方法接收一个routes
数组和全局配置,会返回addRoute
、removeRoute
、getRoutes
、getRecordMatcher
、resolve
等方法。在其内部会遍历routes
并调用addRoute
addRoute
: 添加路由removeRoute
: 移除路由getRoutes
: 获取路由getRecordMatcher
: 获取路由记录匹配器resolve
:解析路由
createRouter
方法创建的实例有以下属性
return {
currentRoute,
listening: true,
addRoute,
removeRoute,
hasRoute,
getRoutes,
resolve,
options,
push,
replace,
go: (step) => routerHistory.go(step),
back: () => go(-1),
forward: () => go(1),
beforeEach: beforeGuards.add,
beforeResolve: beforeResolveGuards.add,
afterEach: afterGuards.add,
onError: errorListeners.add,
isReady,
install,
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
go
、back
、forward
方法本质上调用的都是options.history.go
方法,而这个go
方法本质上还是调用的window.history.go
。addRoute
方法:可以用于动态添加路由,接收两个参数,parentRouteName
和route
;若parentRouteName
为空,则添加到根路由下,否则添加到指定路由下。其内部是调用的matcher
的addRoute
方法。removeRoute
方法:接收一个参数name
,用于删除指定路由。首先会调用matcher
的getRecordMatcher
方法,如果返回有值,则调用matcher
的removeRoute
方法。hasRoute
方法:接收一个参数name
,判断路由是否存在,调用matcher
的getRecordMatcher
方法getRoutes
方法: 返回所有路由,遍历调用matcher
的getRoutes
方法的返回值,取其record
# createWebHistory
createWebHistory
创建一个 history 模式路由, 返回一个 routerHistory 对象。该对象提供了以下方法:go
、replace
、push
、listen
、destory
、pauselisten
等方法以及location
和state
对象。
createWebHistory
方法中主要用到了useHistoryStatenavigation
和useHistoryListeners
方法.
实现步骤: 1.接收一个参数
base
,调用normalizeBase
方法进行路由规范化处理,去除协议和域名部分,确保路由以/
开头和不以/
结尾 2.调用useHistoryStatenavigation
方法,创建一个navigation
对象,用于记录路由变化和状态 3.调用useHistoryListeners
方法,创建一个listeners
对象,用于记录路由变化监听器 4.赋值 2、3 的返回给routerHistory
,并返回
# useHistoryStateNavigation
useHistoryStateNavigation
方法首先会根据window.location
和 base 获取当前的路由值, 然后判断window.history.state
,如果其不为空则调用changeLocation
在其内部调用window.history.replaceState
或者window.history.pushState
,最后改变 state 的值。
useHistoryStateNavigation
方法返回的push
和replace
方法均会调用changeLocation
方法,其中push
会调用两次
# useHistoryListeners
useHistoryListeners
方法接收四个参数base
、调用useHistoryStateNavigation
方法返回的state
、location
属性和replace
方法
其内部实现主要逻辑是监听popstate
和beforeunload
事件,执行相应的路由切换逻辑,从而实现前端路由的控制和管理
popstate
事件:浏览器的历史记录发生变化(用户的执行某些导航操作,如点击浏览器的前进、后退按钮或者通过 javascript 调用history.pushState
、history.replaceState
、history.back()
和history.forward()
等方法时会触发,触发popstate
事件,vue router
内部会执行popStateHandler
函数,popStateHandler
函数主要是判断state
,如果state
存在,则更新当前位置、历史状态并计算位置偏移值;如果state
不存在,则调用replace
方法更新。最后遍历了注册的所有监听器listeners
并执行监听器, 传参为三个:currentLocation.value
:当前位置信息、from
:之前的位置信息、路由变化的对象:delta
、type
:'pop'、direction
:正负表示前进、后退还是未知方向
beforeunload
事件:用于在用户即将离开当前页面(关闭页面、刷新页面、导航到其他页面)时触发,触发该事件时,vue router
会执行beforeUnloadListener
函数,调用history.replaceState
方法
以上两个监听的事件会在destory
函数中移除
# createWebHashHistory
createWebHashHistory
会创建一个 hash 模式的路由,同createWebHistory
一样,接收一个参数base
,会自动给 base 加上#
,再调用createWebHistory
并返回
# createMemoryHistory
createMemoryHistory
会基于内存创建一个 history,主要用于处理服务端渲染 SSR,即不依赖于浏览器的实际 url 地址变化,而是在内存中维护路由历史记录。
createMemoryHistory
返回的是一个routerHistory
对象,这个对象包含replace
、push
、listen
、destroy
、go
方法。createMemoryHistory
内部维护了两个数组listeners
、quue
,listeners
用于记录listen
方法注册的回调函数,queue
用于记录路由历史记录,可以被当作一个路由队列。