【VueRouter 源码学习】第九篇 - router-view 组件的实现
一,前言
上篇,介绍了$route
、$router
与 router-link
组件的实现,主要涉及以下内容:
定义原型方法
$route
和$router
;<router-link>
组件的功能和实现;
本篇,介绍<router-view>
组件的实现;
二,前文回顾
在 VueRouter 实例化时,通过路由匹配器 createMatcher 对路由配置进行扁平化处理;
路由匹配器 createMatcher 中的 match 方法,匹配路由记录并创建路由对象;
将当前匹配路由对象 current,创建为响应式数据;
点击 router-link 组件进行路径切换,调用 transitionTo 匹配新路由记录并更新响应式数据 current,触发视图更新;
点击 router-link 组件进行路径切换时,需要根据最新路由地址匹配到全部路由规则,并递归进行页面的更新渲染操作;
三,函数式组件
router-view 是一个函数式组件,函数式组件有以下特点:
性能高,渲染时没有 this;
functional: true 表示函数式组件;
普通组件,使用组件需要先进行实例化再挂载:new Ctor().$mount();
函数式组件,无需创建实例即可直接使用(相当于 react 中的函数组件);
他们之间唯一的区别就是 render 函数中没有 this,即没有组件状态(没有 data,props 等)
四,<router-view>
组件的实现
1,获取渲染记录数据
在当前组件的父亲 parent 上,存在 $route 属性;
parent.$router 就是 _route,即当前匹配到的路由对象 current 属性;
2,记录递归深度 depth
获取到 $route 属性后,route.matched 即为全部路由匹配记录;
处理逻辑:
app.vue 中包含 router-view 组件,渲染 Home 首页组件;
当点击“跳转至我的”进行路由切换时,app.vue 中的 router-view 渲染 Mine 组件;
当点击“我的-个人信息”进行路由切换时,mine.vue 中的 router-view 渲染 /mine/user 路由对应的组件;
所以,当访问/mine/user 时,将会匹配到三条路由规则: /、/mine、/mine/user;
此时,需要按照上面的描述,依次进行渲染操作;
所以,需要通过记录深度 depth 对应到每一层 router-view 要渲染的内容;
3,处理第一层渲染
当 router-view 组件渲染时,将调用 routerView 组件的 render 方法;
此时,在当前层级(第一层)的 data 属性中,添加自定义属性 data.routerView = true;
第一次渲染时,根据匹配结果与层级深度 depth,需要渲染 route.matched 中的第 0 项;
通过 let record = route.matched[0]
获取对应层级渲染所需的记录;
router-view 有可能只有一层,直接取出来;
若未匹配到记录,record 不存在,直接返回一个空的虚拟节点 empty-vnode 叫注释节点
h()
若匹配到记录,record 有值,进行组件渲染
h(record.component)
,通过 record.component 获取组件;h(record.component):渲染当前组件,当组件渲染时,传入 data 数据,其中 data 包含了之前标识的 routerView 属性;
这样,就完成了第一层 router-view 标签的渲染;
4,处理多层 router-view 渲染
每次 router-view 渲染时,都会在当前 data 中设置 routerView 属性作为标记;
render 函数中的 parent 为当前 router-view 的父标签;
通过循环 parent,判断
parent.$vnode.data.routerView
标识,计算当前渲染的层级深度 depth;获取对应层级的路由记录,进行视图渲染;
相关说明:
parent.$vnode:代表占位符的 vnode;即:组件标签名的虚拟节点;
parent._vnode 指组件的内容;即:实际要渲染的虚拟节点;
以上就实现了 router-view 组件的视图更新操作;
五,结尾
本篇,介绍了 router-view
组件的实现,主要涉及以下内容:
函数式组件的介绍;
router-view 组件的实现:
获取渲染记录;
标记 router-view 层级深度;
根据深度进行 router-view 渲染;
下一篇,介绍 vue-router 的钩子函数;
评论