【vue-rouer源码】系列文章

  1. 【vue-router源码】一、router.install解析
  2. 【vue-router源码】二、createWebHistory、createWebHashHistory、createMemoryHistory源码解析
  3. 【vue-router源码】三、理解Vue-router中的Matcher
  4. 【vue-router源码】四、createRouter源码解析
  5. 【vue-router源码】五、router.addRoute、router.removeRoute、router.hasRoute、router.getRoutes源码分析
  6. 【vue-router源码】六、router.resolve源码解析
  7. 【vue-router源码】七、router.push、router.replace源码解析
  8. 【vue-router源码】八、router.go、router.back、router.forward源码解析
  9. 【vue-router源码】九、全局导航守卫的实现
  10. 【vue-router源码】十、isReady源码解析
  11. 【vue-router源码】十一、onBeforeRouteLeave、onBeforeRouteUpdate源码分析
  12. 【vue-router源码】十二、useRoute、useRouter、useLink源码分析
  13. 【vue-router源码】十三、RouterLink源码分析
  14. 【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中提取parseQuerystringifyQueryhistory属性,如果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
}

然后声明了大量的函数,包括addRouteremoveRoutegetRoutes等,这些函数也就是我们日常使用的addRouteremoveRoute等。

createRouter的最后创建了一个router对象,并将其返回,该对象几乎包含了声明的所有函数。

总结

createRouter函数中声明了一些全局钩子所需的变量和很多函数,这些函数就是我们日常使用的一些方法,如addRouteremoveRoute等,在函数的最后,声明了一个router对象,前面所声明的函数多数都会被包含在这个对象里,最终会将router返回。在router中有个重要的install方法,关于install的过程可以看之前的文章,这里就不再次介绍了。
对于router中的各个函数,会在后续文章中继续介绍。

【vue-router源码】四、createRouter源码解析相关推荐

  1. 异或校验 java_Java生成异或校验码、和校验码、CRC校验码、补码求和校验码四种校验码及校验码匹配工具类...

    Java生成异或校验码.和校验码.CRC校验码.补码求和校验码四种校验码及校验码匹配工具类 /** * 报文校验码验证规则 */ public class Verification { /** * 校 ...

  2. vue router 参数_Vue.js项目开发技术解析

    Vue.js项目开发技术解析 一.Vue.js实例 在一个Vue.js工程中,用于显示内容最基层的实例称之为根实例.通过该实例可以进行页面或组件的更新和显示.对于项目本身而言,无论是什么样的页面,都要 ...

  3. Vue Router 组件内的守卫、导航解析流程

    可以在路由组件内直接定义路由导航守卫(传递给路由配置的) 可用的配置 API beforeRouteEnter 在渲染该组件的对应路由被验证前调用. 此时不能获取组件实例 this , 因为当守卫执行 ...

  4. 【Android 热修复】热修复原理 ( 类加载分析 | 分析 PathClassLoader 源码 | 分析 BaseDexClassLoader 源码 | 分析 PathDexList 源码 )

    文章目录 一.分析 PathClassLoader 源码 二.分析 BaseDexClassLoader 源码 三.分析 PathDexList 源码 四. 源码资源 一.分析 PathClassLo ...

  5. Vue 源码之手写Vue Router

    Vue 源码之手写Vue Router 源码地址:https://github.com/CONOR007/Handwritten-routing 一.Vue Router的两种模式 hash模式实现原 ...

  6. Vue源码 Vue Router(三)matcher 路由匹配器

    Vue源码 Vue Router(三)matcher Vue源码 Vue Router(三)matcher matcher createMatcher addRoutes match 总结 单步调试参 ...

  7. python+vue校园足球联赛管理系统django源码

    本次设计任务是要设计一个足球联赛管理系统,通过这个系统能够满足用户及时浏览各种足球联赛信息.系统的主要功能包括主页.个人中心.用户管理.球队赛程管理.球队信息管理.球员信息管理.打赏球员管理.系统管理 ...

  8. springboot+vue+mysql外卖点餐管理系统源码(包安装+讲解)

     博主介绍:✌在职Java研发工程师.专注于程序设计.源码分享.技术交流.专注于Java技术领域和毕业设计✌ 项目名称 springboot+vue+mysql外卖点餐管理系统源码(包安装+讲解) 视 ...

  9. 基于 SpringBoot + Vue 的物流管理系统(附源码)

    国庆期间哪也没去,在家闲来无事,写了一个基于 SpringBoot + Vue 的物流管理系统,把源码分享给大家,在文章结尾处,自行获取即可~ 一.介绍 基于Java的物流管理系统. 二.软件架构 系 ...

  10. 适合初学者练手的vue小项目(附github源码)

    vue慢慢的成为了前端最受欢迎的框架之一,在很多项目之中开发都能用得到,如今也已经发展到3.0了,可能是因为这个框架可以提高工作效率,因此受到大家的追捧,在之前的文章里面也说过,2019年,大前端学习 ...

最新文章

  1. linux windows 编译安装,Windows下编译安装OpenEXR(x86版本)
  2. 0513JS基础:数组内置方法、数学函数、时间函数
  3. 【题解】 bzoj2748 [HAOI2012]音量调节 (动态规划)
  4. Sun x4500作为文件服务器的调优
  5. 【读书笔记】【独立思考】2018-04-03(1)
  6. c语言查看cpu温度代码_很多程序员都不知道,C语言中还有“快类型”和“小类型”...
  7. RPC框架设计概要-性能
  8. vue+webapi 实现WebSocket 推送
  9. Win10关闭系统自动更新
  10. 虚拟机中使linux系统分辨率变大
  11. pygame.font.Font().render() 计算基线(baseline)的原点(origin)坐标
  12. 树莓派64位系统_玩转树莓派之安装系统
  13. Visual Studio 水晶报表Crystal Reports
  14. 周杰伦 jay《青花瓷》mp3 下载/试听/MV/在线播放
  15. 手工清除U盘里的恶意病毒
  16. PhalAPI学习笔记拓展篇 ——— 基于MySQL数据库交互题目
  17. 软件测试邻居集成,软件测试之集成测试(ppt-3).ppt
  18. 台式计算机的电流是多少,电脑台式机一天耗电大概是多少
  19. Testin云测技术沙龙在沪召开,云监控预警成关注重点
  20. 二进制文件vscode_VS code 的使用

热门文章

  1. 电子罗盘的椭球拟合与椭球变换
  2. 论学习计划的 重要性
  3. JSP统计网站访问人数
  4. 深度技术官网linux,深度系统
  5. java 正则判断二进制_如何在Java正则表达式匹配中使用IsAlphabetic二进制属性?
  6. 【EXCEL】表格中固定行列 冻结窗口怎么是灰色的
  7. oblog后台管理问题
  8. 操盘手怎样于2019年4月17号的二级市场中基于ATR实现开仓平仓
  9. 在MFC程序中使用XML文件配置工具栏
  10. Spring Cloud之赵国的覆灭