vue的matcher_vue源码解析(19)--VueRouter match

上一节我们分析到transitionTo函数(src/history/base.js)

里面执行了match方法,我们来看下match的具体实现:(src/index.js)

它会执行this.matcher.match函数,macther是router中非常重要的概念,在介绍macth方法之前我们先看一下createMatcher方法的实现:(src/index.js),它传入的options.routes就是我们在定义的routes中patch,components等。

方法位置是在(src/create-matcher.js)

它传入的函数参数有routes数组,还有router实例,它的返回值是一个matcher对象,有两个属性,这两个属性分别为两个函数,match函数和addRoutes函数。

createMatcher 实现实际上是定义好多函数,返回了match,以及addRoutes,它的初始化逻辑实际上就一行代码 const { pathList, pathMap, nameMap } = createRouteMap(routes),将我们的routes传入,createRouteMap函数作用就是穿件路由映射表,它的具体实现是在src/create-route-map.js中:

createRouteMap实现的逻辑是定义三个常量pathList, pathMap, nameMap首先会再内存中取,如果取不到就会创建默认数组,空对象。接下来就会遍历我们routes配置项,遍历时调用addRouteRecord:

此方法会首先从routes中拿到我们的path和name,接下来会对route进pathToRegexpOptions正则的判断,然后会对patch和parent进行normalizePath,normalizePath的定义是在src/create-route-map.js

normalizePathnormalizePath中判断如果path[0]为/ 那么就是根路径,直接return,如果父路由为null,也直接return,最后会使用cleanPath对父路径和子路径进行拼接。

我们回到addRouteRecord方法中:

定义了一个RouteRecord,这个是核心逻辑,我们来看传入的几个核心参数:

path是规范化后的路径,它会根据parent的path做计算;regex是一个正则表达式的扩展,它利用了path-to-regexp这个工具库,把path解析成一个正则表达式的扩展。components是一个对象,通常我们在配置中写的component实际上这里会被转换成{components: route.component};instances表示组件的实例,也是一个对象类型;parent表示父的RouteRecord,因为我们配置的时候有时候会配置子路由,所以整个RouteRecord 是树形结构。

当router有children时候:

就会递归的循环子路由,然后子路由调用addRouteRecord,为子路由都创建record。

当执行到叶子节点时候,也就是当没有子节点时候就会执行以下逻辑:

会将record.path push 到 pathList中,然后把record作为key,也就是pathList存储所有的path,pathMap表示一个path到RouteRecord的映射关系,而nameMap表示name到RouteRecord的映射关系,

最终就会产生一个路由映射表:

那么回到我们的createMatcher,也就是创建一张路由映射表。

addRoutes相当于一个动态添加的路由。

我们分析完matcher后回到vuerouter这个类,定义的match函数:

match方法接收 3 个参数,其中raw是RawLocation类型,它可以是一个url字符串,也可以是一个Location对象;currentRoute是Route类型,它表示当前的路径;redirectedFrom和重定向相关,这里先忽略。match方法返回的是一个路径,它的作用是根据传入的raw和当前的路径currentRoute计算出一个新的路径并返回。

然后看一下Location以及RawLocation的定义。

normalizeLocation执行是在util/location.js中:

normalizeLocation方法的作用是根据当前rawlocation,当前的路由currentroute计算出一个新的location,会根据parsePath解析出一个新的路径,它主要处理了raw的两种情况,一种是有params且没有path,一种是有path的,对于第一种情况,如果current有name,则计算出的location也有name。

我们再回到match函数中的具体实现,执行normalizeLocation后就会判断是否有name,如果有的话就根据nameMap生成record,也就是生成一个RouterRecord对象,如果record不存在就返回一个空路径,record.regex.keys生成一个paramNames

接下来就会对比paramNames以及currentRoute.params,将他们的交集params添加到location中

接下来会根据fillParams方法根据record.path和location.path计算出location.path,最后调用_createRoute(record, location, redirectedFrom)去生成一条新路径。

如果name不存在的话,location.path存在,

会对存在的正则表达式进行匹配,如果匹配上的话就会调用_createRoute(record, location, redirectedFrom)生成新的路径

接下来我们来看一下_createRoute函数,它最终会调用createRoute函数

执行stringifyQuery函数,接下来对location.query进行clone操作,定义了一个route对象,这个对象有从location中拿的name ,path,也有从record中拿的meta,最后返回一个route路径调用对象的freeze方法,说明这条路径是不可以修改的。这样match的逻辑就大致梳理完了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值