【vue-router源码】四、createRouter源码解析
【vue-rouer源码】系列文章
- 【vue-router源码】一、router.install解析
- 【vue-router源码】二、createWebHistory、createWebHashHistory、createMemoryHistory源码解析
- 【vue-router源码】三、理解Vue-router中的Matcher
- 【vue-router源码】四、createRouter源码解析
- 【vue-router源码】五、router.addRoute、router.removeRoute、router.hasRoute、router.getRoutes源码分析
- 【vue-router源码】六、router.resolve源码解析
- 【vue-router源码】七、router.push、router.replace源码解析
- 【vue-router源码】八、router.go、router.back、router.forward源码解析
- 【vue-router源码】九、全局导航守卫的实现
- 【vue-router源码】十、isReady源码解析
- 【vue-router源码】十一、onBeforeRouteLeave、onBeforeRouteUpdate源码分析
- 【vue-router源码】十二、useRoute、useRouter、useLink源码分析
- 【vue-router源码】十三、RouterLink源码分析
- 【vue-router源码】十四、RouterView源码分析
目录
- 【vue-rouer源码】系列文章
- 前言
- 使用
- createRouter
- 总结
前言
【vue-router源码】系列文章将带你从0开始了解vue-router
的具体实现。该系列文章源码参考vue-router v4.0.15
。
源码地址:https://github.com/vuejs/router
阅读该文章的前提是你最好了解vue-router
的基本使用,如果你没有使用过的话,可通过vue-router官网学习下。
该篇文章将带你分析createRouter
的实现。
使用
const routerHistory = createWebHistory()
export const router = createRouter({history: routerHistory,strict: true,routes: [{ path: '/home', redirect: '/' },{path: '/',components: { default: Home, other: component },props: { default: to => ({ waited: to.meta.waitedFor }) },},{path: '/nested',alias: '/anidado',component: Nested,name: 'Nested',children: [{path: 'nested',alias: 'a',name: 'NestedNested',component: Nested,children: [{name: 'NestedNestedNested',path: 'nested',component: Nested,},],},{path: 'other',alias: 'otherAlias',component: Nested,name: 'NestedOther',},{path: 'also-as-absolute',alias: '/absolute',name: 'absolute-child',component: Nested,},],},],async scrollBehavior(to, from, savedPosition) {await scrollWaiter.wait()if (savedPosition) {return savedPosition} else {if (to.matched.every((record, i) => from.matched[i] !== record))return { left: 0, top: 0 }}return false},
})
createRouter
在分析createRouter
之前,先来看下它的参数类型:
export interface _PathParserOptions {// 使用正则时区分大小写,默认falsesensitive?: boolean// 是否禁止尾随斜杠,默认falsestrict?: boolean// 正则表达式前应该加^,默认truestart?: boolean// 正则表达式以$结尾,默认为trueend?: boolean
}export type PathParserOptions = Pick<_PathParserOptions,'end' | 'sensitive' | 'strict'
>export interface RouterOptions extends PathParserOptions {history: RouterHistory// 路由表routes: RouteRecordRaw[]// 在页面之间导航时控制滚动行为。可以返回一个 Promise 来延迟滚动。scrollBehavior?: RouterScrollBehavior// 用于自定义如何解析queryparseQuery?: typeof originalParseQuery// 用于自定义查询对象如何转为字符串stringifyQuery?: typeof originalStringifyQuery// 激活RouterLink的默认类linkActiveClass?: string// 精准激活RouterLink的默认类linkExactActiveClass?: string
}
我们来看下createRouter
具体做了什么。createRouter
方法共885(包含空行)行,乍一看可能会觉得方法很复杂,仔细观察,其实很大一部分代码都是声明一些函数。我们可以先暂时抛开这些函数声明看其余部分。
首先会使用createRouterMatcher
方法创建了一个路由匹配器matcher
,从options
中提取parseQuery
、stringifyQuery
、history
属性,如果options
中没有history
,抛出错误。
const matcher = createRouterMatcher(options.routes, options)
const parseQuery = options.parseQuery || originalParseQuery
const stringifyQuery = options.stringifyQuery || originalStringifyQuery
const routerHistory = options.history
if (__DEV__ && !routerHistory)throw new Error('Provide the "history" option when calling "createRouter()":' +' https://next.router.vuejs.org/api/#history.')
紧接着声明了一些全局守卫相关的变量,和一些关于params
的处理方法,其中有关全局守卫的变量都是通过useCallbacks
创建的,params
相关方法通过applyToParams
创建。
// 全局前置守卫相关方法
const beforeGuards = useCallbacks<NavigationGuardWithThis<undefined>>()
// 全局解析守卫相关方法
const beforeResolveGuards = useCallbacks<NavigationGuardWithThis<undefined>>()
// 全局后置钩子方法
const afterGuards = useCallbacks<NavigationHookAfter>()// 当前路由,浅层响应式对象
const currentRoute = shallowRef<RouteLocationNormalizedLoaded>(START_LOCATION_NORMALIZED
)
let pendingLocation: RouteLocation = START_LOCATION_NORMALIZED// 如果浏览器环境下设置了scrollBehavior,那么需要防止页面自动恢复页面位置
// https://developer.mozilla.org/zh-CN/docs/Web/API/History/scrollRestoration
if (isBrowser && options.scrollBehavior && 'scrollRestoration' in history) {history.scrollRestoration = 'manual'
}// 标准化params,转字符串
const normalizeParams = applyToParams.bind(null,paramValue => '' + paramValue
)
// 编码param
const encodeParams = applyToParams.bind(null, encodeParam)
// 解码params
const decodeParams: (params: RouteParams | undefined) => RouteParams =applyToParams.bind(null, decode)
关于useCallbacks
的实现:在useCallbacks
中声明一个handlers
数组用来保存所有添加的方法,useCallbacks
的返回值中包括三个方法:add
(添加一个handler
,并返回一个删除handler
的函数)、list
(返回所有handler
)、reset
(清空所有handler
)
export function useCallbacks<T>() {let handlers: T[] = []function add(handler: T): () => void {handlers.push(handler)return () => {const i = handlers.indexOf(handler)if (i > -1) handlers.splice(i, 1)}}function reset() {handlers = []}return {add,list: () => handlers,reset,}
}
applyToParams
的实现:接收一个处理函数和params
对象,遍历params
对象,并对每一个属性值执行fn
并将结果赋给一个新的对象。
export function applyToParams(fn: (v: string | number | null | undefined) => string,params: RouteParamsRaw | undefined
): RouteParams {const newParams: RouteParams = {}for (const key in params) {const value = params[key]newParams[key] = Array.isArray(value) ? value.map(fn) : fn(value)}return newParams
}
然后声明了大量的函数,包括addRoute
、removeRoute
、getRoutes
等,这些函数也就是我们日常使用的addRoute
、removeRoute
等。
在createRouter
的最后创建了一个router
对象,并将其返回,该对象几乎包含了声明的所有函数。
总结
createRouter
函数中声明了一些全局钩子所需的变量和很多函数,这些函数就是我们日常使用的一些方法,如addRoute
、removeRoute
等,在函数的最后,声明了一个router
对象,前面所声明的函数多数都会被包含在这个对象里,最终会将router
返回。在router
中有个重要的install
方法,关于install
的过程可以看之前的文章,这里就不再次介绍了。
对于router
中的各个函数,会在后续文章中继续介绍。
【vue-router源码】四、createRouter源码解析相关推荐
- 异或校验 java_Java生成异或校验码、和校验码、CRC校验码、补码求和校验码四种校验码及校验码匹配工具类...
Java生成异或校验码.和校验码.CRC校验码.补码求和校验码四种校验码及校验码匹配工具类 /** * 报文校验码验证规则 */ public class Verification { /** * 校 ...
- vue router 参数_Vue.js项目开发技术解析
Vue.js项目开发技术解析 一.Vue.js实例 在一个Vue.js工程中,用于显示内容最基层的实例称之为根实例.通过该实例可以进行页面或组件的更新和显示.对于项目本身而言,无论是什么样的页面,都要 ...
- Vue Router 组件内的守卫、导航解析流程
可以在路由组件内直接定义路由导航守卫(传递给路由配置的) 可用的配置 API beforeRouteEnter 在渲染该组件的对应路由被验证前调用. 此时不能获取组件实例 this , 因为当守卫执行 ...
- 【Android 热修复】热修复原理 ( 类加载分析 | 分析 PathClassLoader 源码 | 分析 BaseDexClassLoader 源码 | 分析 PathDexList 源码 )
文章目录 一.分析 PathClassLoader 源码 二.分析 BaseDexClassLoader 源码 三.分析 PathDexList 源码 四. 源码资源 一.分析 PathClassLo ...
- Vue 源码之手写Vue Router
Vue 源码之手写Vue Router 源码地址:https://github.com/CONOR007/Handwritten-routing 一.Vue Router的两种模式 hash模式实现原 ...
- Vue源码 Vue Router(三)matcher 路由匹配器
Vue源码 Vue Router(三)matcher Vue源码 Vue Router(三)matcher matcher createMatcher addRoutes match 总结 单步调试参 ...
- python+vue校园足球联赛管理系统django源码
本次设计任务是要设计一个足球联赛管理系统,通过这个系统能够满足用户及时浏览各种足球联赛信息.系统的主要功能包括主页.个人中心.用户管理.球队赛程管理.球队信息管理.球员信息管理.打赏球员管理.系统管理 ...
- springboot+vue+mysql外卖点餐管理系统源码(包安装+讲解)
博主介绍:✌在职Java研发工程师.专注于程序设计.源码分享.技术交流.专注于Java技术领域和毕业设计✌ 项目名称 springboot+vue+mysql外卖点餐管理系统源码(包安装+讲解) 视 ...
- 基于 SpringBoot + Vue 的物流管理系统(附源码)
国庆期间哪也没去,在家闲来无事,写了一个基于 SpringBoot + Vue 的物流管理系统,把源码分享给大家,在文章结尾处,自行获取即可~ 一.介绍 基于Java的物流管理系统. 二.软件架构 系 ...
- 适合初学者练手的vue小项目(附github源码)
vue慢慢的成为了前端最受欢迎的框架之一,在很多项目之中开发都能用得到,如今也已经发展到3.0了,可能是因为这个框架可以提高工作效率,因此受到大家的追捧,在之前的文章里面也说过,2019年,大前端学习 ...
最新文章
- linux windows 编译安装,Windows下编译安装OpenEXR(x86版本)
- 0513JS基础:数组内置方法、数学函数、时间函数
- 【题解】 bzoj2748 [HAOI2012]音量调节 (动态规划)
- Sun x4500作为文件服务器的调优
- 【读书笔记】【独立思考】2018-04-03(1)
- c语言查看cpu温度代码_很多程序员都不知道,C语言中还有“快类型”和“小类型”...
- RPC框架设计概要-性能
- vue+webapi 实现WebSocket 推送
- Win10关闭系统自动更新
- 虚拟机中使linux系统分辨率变大
- pygame.font.Font().render() 计算基线(baseline)的原点(origin)坐标
- 树莓派64位系统_玩转树莓派之安装系统
- Visual Studio 水晶报表Crystal Reports
- 周杰伦 jay《青花瓷》mp3 下载/试听/MV/在线播放
- 手工清除U盘里的恶意病毒
- PhalAPI学习笔记拓展篇 ——— 基于MySQL数据库交互题目
- 软件测试邻居集成,软件测试之集成测试(ppt-3).ppt
- 台式计算机的电流是多少,电脑台式机一天耗电大概是多少
- Testin云测技术沙龙在沪召开,云监控预警成关注重点
- 二进制文件vscode_VS code 的使用